fortran-src 0.8.0 → 0.9.0
raw patch · 86 files changed
+12235/−12504 lines, 86 filesdep +eitherPVP ok
version bump matches the API change (PVP)
Dependencies added: either
API changes (from Hackage documentation)
- Language.Fortran.AST: instance Data.Data.Data a => Data.Data.Data (Language.Fortran.AST.Comment a)
- Language.Fortran.AST: instance GHC.Classes.Eq (Language.Fortran.AST.Comment a)
- Language.Fortran.AST: instance GHC.Generics.Generic (Language.Fortran.AST.Comment a)
- Language.Fortran.AST: instance GHC.Show.Show (Language.Fortran.AST.Comment a)
- Language.Fortran.Lexer.FixedForm: AlexInput :: ByteString -> Int -> Position -> [Word8] -> Char -> Lexeme -> Int -> Int -> Maybe Token -> [Token] -> Bool -> Bool -> FortranVersion -> AlexInput
- Language.Fortran.Lexer.FixedForm: TAmpersand :: SrcSpan -> Token
- Language.Fortran.Lexer.FixedForm: TAssign :: SrcSpan -> Token
- Language.Fortran.Lexer.FixedForm: TAutomatic :: SrcSpan -> Token
- Language.Fortran.Lexer.FixedForm: TBackspace :: SrcSpan -> Token
- Language.Fortran.Lexer.FixedForm: TBlob :: SrcSpan -> String -> Token
- Language.Fortran.Lexer.FixedForm: TBlockData :: SrcSpan -> Token
- Language.Fortran.Lexer.FixedForm: TBool :: SrcSpan -> Bool -> Token
- Language.Fortran.Lexer.FixedForm: TBozLiteral :: SrcSpan -> Boz -> Token
- Language.Fortran.Lexer.FixedForm: TCall :: SrcSpan -> Token
- Language.Fortran.Lexer.FixedForm: TCase :: SrcSpan -> Token
- Language.Fortran.Lexer.FixedForm: TCaseDefault :: SrcSpan -> Token
- Language.Fortran.Lexer.FixedForm: TClose :: SrcSpan -> Token
- Language.Fortran.Lexer.FixedForm: TColon :: SrcSpan -> Token
- Language.Fortran.Lexer.FixedForm: TComma :: SrcSpan -> Token
- Language.Fortran.Lexer.FixedForm: TComment :: SrcSpan -> String -> Token
- Language.Fortran.Lexer.FixedForm: TCommon :: SrcSpan -> Token
- Language.Fortran.Lexer.FixedForm: TContinue :: SrcSpan -> Token
- Language.Fortran.Lexer.FixedForm: TCycle :: SrcSpan -> Token
- Language.Fortran.Lexer.FixedForm: TData :: SrcSpan -> Token
- Language.Fortran.Lexer.FixedForm: TDimension :: SrcSpan -> Token
- Language.Fortran.Lexer.FixedForm: TDo :: SrcSpan -> Token
- Language.Fortran.Lexer.FixedForm: TDoWhile :: SrcSpan -> Token
- Language.Fortran.Lexer.FixedForm: TDot :: SrcSpan -> Token
- Language.Fortran.Lexer.FixedForm: TEOF :: SrcSpan -> Token
- Language.Fortran.Lexer.FixedForm: TElse :: SrcSpan -> Token
- Language.Fortran.Lexer.FixedForm: TElsif :: SrcSpan -> Token
- Language.Fortran.Lexer.FixedForm: TEnd :: SrcSpan -> Token
- Language.Fortran.Lexer.FixedForm: TEndDo :: SrcSpan -> Token
- Language.Fortran.Lexer.FixedForm: TEndFunction :: SrcSpan -> Token
- Language.Fortran.Lexer.FixedForm: TEndMap :: SrcSpan -> Token
- Language.Fortran.Lexer.FixedForm: TEndProgram :: SrcSpan -> Token
- Language.Fortran.Lexer.FixedForm: TEndSelect :: SrcSpan -> Token
- Language.Fortran.Lexer.FixedForm: TEndStructure :: SrcSpan -> Token
- Language.Fortran.Lexer.FixedForm: TEndSubroutine :: SrcSpan -> Token
- Language.Fortran.Lexer.FixedForm: TEndUnion :: SrcSpan -> Token
- Language.Fortran.Lexer.FixedForm: TEndfile :: SrcSpan -> Token
- Language.Fortran.Lexer.FixedForm: TEndif :: SrcSpan -> Token
- Language.Fortran.Lexer.FixedForm: TEntry :: SrcSpan -> Token
- Language.Fortran.Lexer.FixedForm: TEquivalence :: SrcSpan -> Token
- Language.Fortran.Lexer.FixedForm: TExit :: SrcSpan -> Token
- Language.Fortran.Lexer.FixedForm: TExponent :: SrcSpan -> String -> Token
- Language.Fortran.Lexer.FixedForm: TExternal :: SrcSpan -> Token
- Language.Fortran.Lexer.FixedForm: TFormat :: SrcSpan -> Token
- Language.Fortran.Lexer.FixedForm: TFunction :: SrcSpan -> Token
- Language.Fortran.Lexer.FixedForm: TGoto :: SrcSpan -> Token
- Language.Fortran.Lexer.FixedForm: THollerith :: SrcSpan -> String -> Token
- Language.Fortran.Lexer.FixedForm: TId :: SrcSpan -> String -> Token
- Language.Fortran.Lexer.FixedForm: TIf :: SrcSpan -> Token
- Language.Fortran.Lexer.FixedForm: TImplicit :: SrcSpan -> Token
- Language.Fortran.Lexer.FixedForm: TInclude :: SrcSpan -> Token
- Language.Fortran.Lexer.FixedForm: TInquire :: SrcSpan -> Token
- Language.Fortran.Lexer.FixedForm: TInt :: SrcSpan -> String -> Token
- Language.Fortran.Lexer.FixedForm: TIntrinsic :: SrcSpan -> Token
- Language.Fortran.Lexer.FixedForm: TLabel :: SrcSpan -> String -> Token
- Language.Fortran.Lexer.FixedForm: TLeftArrayPar :: SrcSpan -> Token
- Language.Fortran.Lexer.FixedForm: TLeftPar :: SrcSpan -> Token
- Language.Fortran.Lexer.FixedForm: TMap :: SrcSpan -> Token
- Language.Fortran.Lexer.FixedForm: TNewline :: SrcSpan -> Token
- Language.Fortran.Lexer.FixedForm: TNone :: SrcSpan -> Token
- Language.Fortran.Lexer.FixedForm: TOpAnd :: SrcSpan -> Token
- Language.Fortran.Lexer.FixedForm: TOpAssign :: SrcSpan -> Token
- Language.Fortran.Lexer.FixedForm: TOpEQ :: SrcSpan -> Token
- Language.Fortran.Lexer.FixedForm: TOpEquivalent :: SrcSpan -> Token
- Language.Fortran.Lexer.FixedForm: TOpExp :: SrcSpan -> Token
- Language.Fortran.Lexer.FixedForm: TOpGE :: SrcSpan -> Token
- Language.Fortran.Lexer.FixedForm: TOpGT :: SrcSpan -> Token
- Language.Fortran.Lexer.FixedForm: TOpLE :: SrcSpan -> Token
- Language.Fortran.Lexer.FixedForm: TOpLT :: SrcSpan -> Token
- Language.Fortran.Lexer.FixedForm: TOpMinus :: SrcSpan -> Token
- Language.Fortran.Lexer.FixedForm: TOpNE :: SrcSpan -> Token
- Language.Fortran.Lexer.FixedForm: TOpNot :: SrcSpan -> Token
- Language.Fortran.Lexer.FixedForm: TOpNotEquivalent :: SrcSpan -> Token
- Language.Fortran.Lexer.FixedForm: TOpOr :: SrcSpan -> Token
- Language.Fortran.Lexer.FixedForm: TOpPlus :: SrcSpan -> Token
- Language.Fortran.Lexer.FixedForm: TOpXOr :: SrcSpan -> Token
- Language.Fortran.Lexer.FixedForm: TOpen :: SrcSpan -> Token
- Language.Fortran.Lexer.FixedForm: TParameter :: SrcSpan -> Token
- Language.Fortran.Lexer.FixedForm: TPause :: SrcSpan -> Token
- Language.Fortran.Lexer.FixedForm: TPercent :: SrcSpan -> Token
- Language.Fortran.Lexer.FixedForm: TPointer :: SrcSpan -> Token
- Language.Fortran.Lexer.FixedForm: TPrint :: SrcSpan -> Token
- Language.Fortran.Lexer.FixedForm: TProgram :: SrcSpan -> Token
- Language.Fortran.Lexer.FixedForm: TRead :: SrcSpan -> Token
- Language.Fortran.Lexer.FixedForm: TRecord :: SrcSpan -> Token
- Language.Fortran.Lexer.FixedForm: TReturn :: SrcSpan -> Token
- Language.Fortran.Lexer.FixedForm: TRewind :: SrcSpan -> Token
- Language.Fortran.Lexer.FixedForm: TRightArrayPar :: SrcSpan -> Token
- Language.Fortran.Lexer.FixedForm: TRightPar :: SrcSpan -> Token
- Language.Fortran.Lexer.FixedForm: TSave :: SrcSpan -> Token
- Language.Fortran.Lexer.FixedForm: TSelectCase :: SrcSpan -> Token
- Language.Fortran.Lexer.FixedForm: TSlash :: SrcSpan -> Token
- Language.Fortran.Lexer.FixedForm: TStar :: SrcSpan -> Token
- Language.Fortran.Lexer.FixedForm: TStatic :: SrcSpan -> Token
- Language.Fortran.Lexer.FixedForm: TStop :: SrcSpan -> Token
- Language.Fortran.Lexer.FixedForm: TString :: SrcSpan -> String -> Token
- Language.Fortran.Lexer.FixedForm: TStructure :: SrcSpan -> Token
- Language.Fortran.Lexer.FixedForm: TSubroutine :: SrcSpan -> Token
- Language.Fortran.Lexer.FixedForm: TThen :: SrcSpan -> Token
- Language.Fortran.Lexer.FixedForm: TTo :: SrcSpan -> Token
- Language.Fortran.Lexer.FixedForm: TType :: SrcSpan -> String -> Token
- Language.Fortran.Lexer.FixedForm: TTypePrint :: SrcSpan -> Token
- Language.Fortran.Lexer.FixedForm: TUnion :: SrcSpan -> Token
- Language.Fortran.Lexer.FixedForm: TWhile :: SrcSpan -> Token
- Language.Fortran.Lexer.FixedForm: TWrite :: SrcSpan -> Token
- Language.Fortran.Lexer.FixedForm: [aiBytes] :: AlexInput -> [Word8]
- Language.Fortran.Lexer.FixedForm: [aiCaseSensitive] :: AlexInput -> Bool
- Language.Fortran.Lexer.FixedForm: [aiEndOffset] :: AlexInput -> Int
- Language.Fortran.Lexer.FixedForm: [aiFortranVersion] :: AlexInput -> FortranVersion
- Language.Fortran.Lexer.FixedForm: [aiInFormat] :: AlexInput -> Bool
- Language.Fortran.Lexer.FixedForm: [aiLexeme] :: AlexInput -> Lexeme
- Language.Fortran.Lexer.FixedForm: [aiPosition] :: AlexInput -> Position
- Language.Fortran.Lexer.FixedForm: [aiPreviousChar] :: AlexInput -> Char
- Language.Fortran.Lexer.FixedForm: [aiPreviousToken] :: AlexInput -> Maybe Token
- Language.Fortran.Lexer.FixedForm: [aiPreviousTokensInLine] :: AlexInput -> [Token]
- Language.Fortran.Lexer.FixedForm: [aiSourceBytes] :: AlexInput -> ByteString
- Language.Fortran.Lexer.FixedForm: [aiStartCode] :: AlexInput -> Int
- Language.Fortran.Lexer.FixedForm: [aiWhiteSensitiveCharCount] :: AlexInput -> Int
- Language.Fortran.Lexer.FixedForm: collectFixedTokens :: FortranVersion -> ByteString -> [Token]
- Language.Fortran.Lexer.FixedForm: collectFixedTokensSafe :: FortranVersion -> ByteString -> Maybe [Token]
- Language.Fortran.Lexer.FixedForm: data AlexInput
- Language.Fortran.Lexer.FixedForm: data Token
- Language.Fortran.Lexer.FixedForm: initParseState :: ByteString -> FortranVersion -> String -> ParseState AlexInput
- Language.Fortran.Lexer.FixedForm: instance Data.Data.Data Language.Fortran.Lexer.FixedForm.Token
- Language.Fortran.Lexer.FixedForm: instance GHC.Classes.Eq Language.Fortran.Lexer.FixedForm.Token
- Language.Fortran.Lexer.FixedForm: instance GHC.Classes.Ord Language.Fortran.Lexer.FixedForm.Token
- Language.Fortran.Lexer.FixedForm: instance GHC.Generics.Generic Language.Fortran.Lexer.FixedForm.Token
- Language.Fortran.Lexer.FixedForm: instance GHC.Show.Show Language.Fortran.Lexer.FixedForm.AlexInput
- Language.Fortran.Lexer.FixedForm: instance GHC.Show.Show Language.Fortran.Lexer.FixedForm.Lexeme
- Language.Fortran.Lexer.FixedForm: instance GHC.Show.Show Language.Fortran.Lexer.FixedForm.Token
- Language.Fortran.Lexer.FixedForm: instance Language.Fortran.ParserMonad.LastToken Language.Fortran.Lexer.FixedForm.AlexInput Language.Fortran.Lexer.FixedForm.Token
- Language.Fortran.Lexer.FixedForm: instance Language.Fortran.ParserMonad.Tok Language.Fortran.Lexer.FixedForm.Token
- Language.Fortran.Lexer.FixedForm: instance Language.Fortran.Util.FirstParameter.FirstParameter Language.Fortran.Lexer.FixedForm.Token Language.Fortran.Util.Position.SrcSpan
- Language.Fortran.Lexer.FixedForm: instance Language.Fortran.Util.FirstParameter.FirstParameter Language.Fortran.Lexer.FixedForm.Token Language.Fortran.Util.Position.SrcSpan => Language.Fortran.Util.Position.Spanned Language.Fortran.Lexer.FixedForm.Token
- Language.Fortran.Lexer.FixedForm: instance Language.Fortran.Util.Position.Loc Language.Fortran.Lexer.FixedForm.AlexInput
- Language.Fortran.Lexer.FixedForm: instance Language.Fortran.Util.Position.Spanned Language.Fortran.Lexer.FixedForm.Lexeme
- Language.Fortran.Lexer.FixedForm: lexN :: Int -> LexAction (Maybe String)
- Language.Fortran.Lexer.FixedForm: lexemeMatch :: Lexeme -> String
- Language.Fortran.Lexer.FixedForm: lexer :: (Token -> LexAction a) -> LexAction a
- Language.Fortran.Lexer.FixedForm: type LexAction a = Parse AlexInput Token a
- Language.Fortran.Lexer.FixedForm.Utils: makeReal :: Maybe Token -> Maybe Token -> Maybe Token -> Maybe (SrcSpan, String) -> Expression A0
- Language.Fortran.Lexer.FreeForm: AlexA# :: Addr# -> AlexAddr
- Language.Fortran.Lexer.FreeForm: AlexAcc :: Int -> AlexAcc user
- Language.Fortran.Lexer.FreeForm: AlexAccNone :: AlexAcc user
- Language.Fortran.Lexer.FreeForm: AlexAccPred :: Int -> AlexAccPred user -> AlexAcc user -> AlexAcc user
- Language.Fortran.Lexer.FreeForm: AlexAccSkip :: AlexAcc user
- Language.Fortran.Lexer.FreeForm: AlexAccSkipPred :: AlexAccPred user -> AlexAcc user -> AlexAcc user
- Language.Fortran.Lexer.FreeForm: AlexEOF :: AlexReturn a
- Language.Fortran.Lexer.FreeForm: AlexError :: !AlexInput -> AlexReturn a
- Language.Fortran.Lexer.FreeForm: AlexInput :: !ByteString -> {-# UNPACK #-} !Position -> {-# UNPACK #-} !Int -> {-# UNPACK #-} !Char -> {-# UNPACK #-} !Lexeme -> {-# UNPACK #-} !StartCode -> !Maybe Token -> ![Token] -> AlexInput
- Language.Fortran.Lexer.FreeForm: AlexLastAcc :: !Int -> !AlexInput -> !Int -> AlexLastAcc
- Language.Fortran.Lexer.FreeForm: AlexLastSkip :: !AlexInput -> !Int -> AlexLastAcc
- Language.Fortran.Lexer.FreeForm: AlexNone :: AlexLastAcc
- Language.Fortran.Lexer.FreeForm: AlexSkip :: !AlexInput -> !Int -> AlexReturn a
- Language.Fortran.Lexer.FreeForm: AlexToken :: !AlexInput -> !Int -> a -> AlexReturn a
- Language.Fortran.Lexer.FreeForm: Char :: Move
- Language.Fortran.Lexer.FreeForm: Continuation :: Move
- Language.Fortran.Lexer.FreeForm: Lexeme :: !String -> {-# UNPACK #-} !Position -> {-# UNPACK #-} !Position -> !Bool -> Lexeme
- Language.Fortran.Lexer.FreeForm: Newline :: Move
- Language.Fortran.Lexer.FreeForm: Return :: StartCodeStatus
- Language.Fortran.Lexer.FreeForm: Stable :: StartCodeStatus
- Language.Fortran.Lexer.FreeForm: StartCode :: {-# UNPACK #-} !Int -> !StartCodeStatus -> StartCode
- Language.Fortran.Lexer.FreeForm: TAbstract :: SrcSpan -> Token
- Language.Fortran.Lexer.FreeForm: TAllocatable :: SrcSpan -> Token
- Language.Fortran.Lexer.FreeForm: TAllocate :: SrcSpan -> Token
- Language.Fortran.Lexer.FreeForm: TArrow :: SrcSpan -> Token
- Language.Fortran.Lexer.FreeForm: TAssign :: SrcSpan -> Token
- Language.Fortran.Lexer.FreeForm: TAssignment :: SrcSpan -> Token
- Language.Fortran.Lexer.FreeForm: TAssociate :: SrcSpan -> Token
- Language.Fortran.Lexer.FreeForm: TAsynchronous :: SrcSpan -> Token
- Language.Fortran.Lexer.FreeForm: TBackspace :: SrcSpan -> Token
- Language.Fortran.Lexer.FreeForm: TBind :: SrcSpan -> Token
- Language.Fortran.Lexer.FreeForm: TBlob :: SrcSpan -> String -> Token
- Language.Fortran.Lexer.FreeForm: TBlockData :: SrcSpan -> Token
- Language.Fortran.Lexer.FreeForm: TBozLiteral :: SrcSpan -> Boz -> Token
- Language.Fortran.Lexer.FreeForm: TC :: SrcSpan -> Token
- Language.Fortran.Lexer.FreeForm: TCall :: SrcSpan -> Token
- Language.Fortran.Lexer.FreeForm: TCase :: SrcSpan -> Token
- Language.Fortran.Lexer.FreeForm: TCharacter :: SrcSpan -> Token
- Language.Fortran.Lexer.FreeForm: TClass :: SrcSpan -> Token
- Language.Fortran.Lexer.FreeForm: TClose :: SrcSpan -> Token
- Language.Fortran.Lexer.FreeForm: TColon :: SrcSpan -> Token
- Language.Fortran.Lexer.FreeForm: TComma :: SrcSpan -> Token
- Language.Fortran.Lexer.FreeForm: TComma2 :: SrcSpan -> Token
- Language.Fortran.Lexer.FreeForm: TComment :: SrcSpan -> String -> Token
- Language.Fortran.Lexer.FreeForm: TCommon :: SrcSpan -> Token
- Language.Fortran.Lexer.FreeForm: TComplex :: SrcSpan -> Token
- Language.Fortran.Lexer.FreeForm: TContains :: SrcSpan -> Token
- Language.Fortran.Lexer.FreeForm: TContinue :: SrcSpan -> Token
- Language.Fortran.Lexer.FreeForm: TCycle :: SrcSpan -> Token
- Language.Fortran.Lexer.FreeForm: TData :: SrcSpan -> Token
- Language.Fortran.Lexer.FreeForm: TDeallocate :: SrcSpan -> Token
- Language.Fortran.Lexer.FreeForm: TDefault :: SrcSpan -> Token
- Language.Fortran.Lexer.FreeForm: TDimension :: SrcSpan -> Token
- Language.Fortran.Lexer.FreeForm: TDo :: SrcSpan -> Token
- Language.Fortran.Lexer.FreeForm: TDoubleColon :: SrcSpan -> Token
- Language.Fortran.Lexer.FreeForm: TDoublePrecision :: SrcSpan -> Token
- Language.Fortran.Lexer.FreeForm: TEOF :: SrcSpan -> Token
- Language.Fortran.Lexer.FreeForm: TElemental :: SrcSpan -> Token
- Language.Fortran.Lexer.FreeForm: TElse :: SrcSpan -> Token
- Language.Fortran.Lexer.FreeForm: TElsewhere :: SrcSpan -> Token
- Language.Fortran.Lexer.FreeForm: TElsif :: SrcSpan -> Token
- Language.Fortran.Lexer.FreeForm: TEnd :: SrcSpan -> Token
- Language.Fortran.Lexer.FreeForm: TEndAssociate :: SrcSpan -> Token
- Language.Fortran.Lexer.FreeForm: TEndBlockData :: SrcSpan -> Token
- Language.Fortran.Lexer.FreeForm: TEndDo :: SrcSpan -> Token
- Language.Fortran.Lexer.FreeForm: TEndEnum :: SrcSpan -> Token
- Language.Fortran.Lexer.FreeForm: TEndForall :: SrcSpan -> Token
- Language.Fortran.Lexer.FreeForm: TEndFunction :: SrcSpan -> Token
- Language.Fortran.Lexer.FreeForm: TEndIf :: SrcSpan -> Token
- Language.Fortran.Lexer.FreeForm: TEndInterface :: SrcSpan -> Token
- Language.Fortran.Lexer.FreeForm: TEndModule :: SrcSpan -> Token
- Language.Fortran.Lexer.FreeForm: TEndProgram :: SrcSpan -> Token
- Language.Fortran.Lexer.FreeForm: TEndSelect :: SrcSpan -> Token
- Language.Fortran.Lexer.FreeForm: TEndSubroutine :: SrcSpan -> Token
- Language.Fortran.Lexer.FreeForm: TEndType :: SrcSpan -> Token
- Language.Fortran.Lexer.FreeForm: TEndWhere :: SrcSpan -> Token
- Language.Fortran.Lexer.FreeForm: TEndfile :: SrcSpan -> Token
- Language.Fortran.Lexer.FreeForm: TEntry :: SrcSpan -> Token
- Language.Fortran.Lexer.FreeForm: TEnum :: SrcSpan -> Token
- Language.Fortran.Lexer.FreeForm: TEnumerator :: SrcSpan -> Token
- Language.Fortran.Lexer.FreeForm: TEquivalence :: SrcSpan -> Token
- Language.Fortran.Lexer.FreeForm: TErr :: SrcSpan -> Token
- Language.Fortran.Lexer.FreeForm: TErrMsg :: SrcSpan -> Token
- Language.Fortran.Lexer.FreeForm: TExit :: SrcSpan -> Token
- Language.Fortran.Lexer.FreeForm: TExternal :: SrcSpan -> Token
- Language.Fortran.Lexer.FreeForm: TFlush :: SrcSpan -> Token
- Language.Fortran.Lexer.FreeForm: TForall :: SrcSpan -> Token
- Language.Fortran.Lexer.FreeForm: TFormat :: SrcSpan -> Token
- Language.Fortran.Lexer.FreeForm: TFunction :: SrcSpan -> Token
- Language.Fortran.Lexer.FreeForm: TGoto :: SrcSpan -> Token
- Language.Fortran.Lexer.FreeForm: TIOMsg :: SrcSpan -> Token
- Language.Fortran.Lexer.FreeForm: TIOStat :: SrcSpan -> Token
- Language.Fortran.Lexer.FreeForm: TId :: SrcSpan -> String -> Token
- Language.Fortran.Lexer.FreeForm: TIf :: SrcSpan -> Token
- Language.Fortran.Lexer.FreeForm: TImplicit :: SrcSpan -> Token
- Language.Fortran.Lexer.FreeForm: TImport :: SrcSpan -> Token
- Language.Fortran.Lexer.FreeForm: TIn :: SrcSpan -> Token
- Language.Fortran.Lexer.FreeForm: TInOut :: SrcSpan -> Token
- Language.Fortran.Lexer.FreeForm: TInclude :: SrcSpan -> Token
- Language.Fortran.Lexer.FreeForm: TInquire :: SrcSpan -> Token
- Language.Fortran.Lexer.FreeForm: TInteger :: SrcSpan -> Token
- Language.Fortran.Lexer.FreeForm: TIntegerLiteral :: SrcSpan -> String -> Token
- Language.Fortran.Lexer.FreeForm: TIntent :: SrcSpan -> Token
- Language.Fortran.Lexer.FreeForm: TInterface :: SrcSpan -> Token
- Language.Fortran.Lexer.FreeForm: TIntrinsic :: SrcSpan -> Token
- Language.Fortran.Lexer.FreeForm: TKind :: SrcSpan -> Token
- Language.Fortran.Lexer.FreeForm: TLeftInitPar :: SrcSpan -> Token
- Language.Fortran.Lexer.FreeForm: TLeftPar :: SrcSpan -> Token
- Language.Fortran.Lexer.FreeForm: TLeftPar2 :: SrcSpan -> Token
- Language.Fortran.Lexer.FreeForm: TLen :: SrcSpan -> Token
- Language.Fortran.Lexer.FreeForm: TLogical :: SrcSpan -> Token
- Language.Fortran.Lexer.FreeForm: TLogicalLiteral :: SrcSpan -> Bool -> Token
- Language.Fortran.Lexer.FreeForm: TModule :: SrcSpan -> Token
- Language.Fortran.Lexer.FreeForm: TModuleProcedure :: SrcSpan -> Token
- Language.Fortran.Lexer.FreeForm: TName :: SrcSpan -> Token
- Language.Fortran.Lexer.FreeForm: TNamelist :: SrcSpan -> Token
- Language.Fortran.Lexer.FreeForm: TNewline :: SrcSpan -> Token
- Language.Fortran.Lexer.FreeForm: TNonIntrinsic :: SrcSpan -> Token
- Language.Fortran.Lexer.FreeForm: TNone :: SrcSpan -> Token
- Language.Fortran.Lexer.FreeForm: TNullify :: SrcSpan -> Token
- Language.Fortran.Lexer.FreeForm: TOnly :: SrcSpan -> Token
- Language.Fortran.Lexer.FreeForm: TOpAnd :: SrcSpan -> Token
- Language.Fortran.Lexer.FreeForm: TOpAssign :: SrcSpan -> Token
- Language.Fortran.Lexer.FreeForm: TOpCustom :: SrcSpan -> String -> Token
- Language.Fortran.Lexer.FreeForm: TOpDivision :: SrcSpan -> Token
- Language.Fortran.Lexer.FreeForm: TOpEQ :: SrcSpan -> Token
- Language.Fortran.Lexer.FreeForm: TOpEquivalent :: SrcSpan -> Token
- Language.Fortran.Lexer.FreeForm: TOpExp :: SrcSpan -> Token
- Language.Fortran.Lexer.FreeForm: TOpGE :: SrcSpan -> Token
- Language.Fortran.Lexer.FreeForm: TOpGT :: SrcSpan -> Token
- Language.Fortran.Lexer.FreeForm: TOpLE :: SrcSpan -> Token
- Language.Fortran.Lexer.FreeForm: TOpLT :: SrcSpan -> Token
- Language.Fortran.Lexer.FreeForm: TOpMinus :: SrcSpan -> Token
- Language.Fortran.Lexer.FreeForm: TOpNE :: SrcSpan -> Token
- Language.Fortran.Lexer.FreeForm: TOpNot :: SrcSpan -> Token
- Language.Fortran.Lexer.FreeForm: TOpNotEquivalent :: SrcSpan -> Token
- Language.Fortran.Lexer.FreeForm: TOpOr :: SrcSpan -> Token
- Language.Fortran.Lexer.FreeForm: TOpPlus :: SrcSpan -> Token
- Language.Fortran.Lexer.FreeForm: TOpen :: SrcSpan -> Token
- Language.Fortran.Lexer.FreeForm: TOperator :: SrcSpan -> Token
- Language.Fortran.Lexer.FreeForm: TOptional :: SrcSpan -> Token
- Language.Fortran.Lexer.FreeForm: TOut :: SrcSpan -> Token
- Language.Fortran.Lexer.FreeForm: TParameter :: SrcSpan -> Token
- Language.Fortran.Lexer.FreeForm: TPause :: SrcSpan -> Token
- Language.Fortran.Lexer.FreeForm: TPercent :: SrcSpan -> Token
- Language.Fortran.Lexer.FreeForm: TPointer :: SrcSpan -> Token
- Language.Fortran.Lexer.FreeForm: TPrint :: SrcSpan -> Token
- Language.Fortran.Lexer.FreeForm: TPrivate :: SrcSpan -> Token
- Language.Fortran.Lexer.FreeForm: TProcedure :: SrcSpan -> Token
- Language.Fortran.Lexer.FreeForm: TProgram :: SrcSpan -> Token
- Language.Fortran.Lexer.FreeForm: TProtected :: SrcSpan -> Token
- Language.Fortran.Lexer.FreeForm: TPublic :: SrcSpan -> Token
- Language.Fortran.Lexer.FreeForm: TPure :: SrcSpan -> Token
- Language.Fortran.Lexer.FreeForm: TRead :: SrcSpan -> Token
- Language.Fortran.Lexer.FreeForm: TReal :: SrcSpan -> Token
- Language.Fortran.Lexer.FreeForm: TRealLiteral :: SrcSpan -> RealLit -> Token
- Language.Fortran.Lexer.FreeForm: TRecursive :: SrcSpan -> Token
- Language.Fortran.Lexer.FreeForm: TResult :: SrcSpan -> Token
- Language.Fortran.Lexer.FreeForm: TReturn :: SrcSpan -> Token
- Language.Fortran.Lexer.FreeForm: TRewind :: SrcSpan -> Token
- Language.Fortran.Lexer.FreeForm: TRightInitPar :: SrcSpan -> Token
- Language.Fortran.Lexer.FreeForm: TRightPar :: SrcSpan -> Token
- Language.Fortran.Lexer.FreeForm: TSave :: SrcSpan -> Token
- Language.Fortran.Lexer.FreeForm: TSelectCase :: SrcSpan -> Token
- Language.Fortran.Lexer.FreeForm: TSemiColon :: SrcSpan -> Token
- Language.Fortran.Lexer.FreeForm: TSequence :: SrcSpan -> Token
- Language.Fortran.Lexer.FreeForm: TSlash :: SrcSpan -> Token
- Language.Fortran.Lexer.FreeForm: TSource :: SrcSpan -> Token
- Language.Fortran.Lexer.FreeForm: TStar :: SrcSpan -> Token
- Language.Fortran.Lexer.FreeForm: TStat :: SrcSpan -> Token
- Language.Fortran.Lexer.FreeForm: TStop :: SrcSpan -> Token
- Language.Fortran.Lexer.FreeForm: TString :: SrcSpan -> String -> Token
- Language.Fortran.Lexer.FreeForm: TSubroutine :: SrcSpan -> Token
- Language.Fortran.Lexer.FreeForm: TTarget :: SrcSpan -> Token
- Language.Fortran.Lexer.FreeForm: TThen :: SrcSpan -> Token
- Language.Fortran.Lexer.FreeForm: TTo :: SrcSpan -> Token
- Language.Fortran.Lexer.FreeForm: TType :: SrcSpan -> Token
- Language.Fortran.Lexer.FreeForm: TUnderscore :: SrcSpan -> Token
- Language.Fortran.Lexer.FreeForm: TUnit :: SrcSpan -> Token
- Language.Fortran.Lexer.FreeForm: TUse :: SrcSpan -> Token
- Language.Fortran.Lexer.FreeForm: TValue :: SrcSpan -> Token
- Language.Fortran.Lexer.FreeForm: TVolatile :: SrcSpan -> Token
- Language.Fortran.Lexer.FreeForm: TWhere :: SrcSpan -> Token
- Language.Fortran.Lexer.FreeForm: TWhile :: SrcSpan -> Token
- Language.Fortran.Lexer.FreeForm: TWrite :: SrcSpan -> Token
- Language.Fortran.Lexer.FreeForm: User :: FortranVersion -> ParanthesesCount -> User
- Language.Fortran.Lexer.FreeForm: [aiEndOffset] :: AlexInput -> {-# UNPACK #-} !Int
- Language.Fortran.Lexer.FreeForm: [aiLexeme] :: AlexInput -> {-# UNPACK #-} !Lexeme
- Language.Fortran.Lexer.FreeForm: [aiPosition] :: AlexInput -> {-# UNPACK #-} !Position
- Language.Fortran.Lexer.FreeForm: [aiPreviousChar] :: AlexInput -> {-# UNPACK #-} !Char
- Language.Fortran.Lexer.FreeForm: [aiPreviousToken] :: AlexInput -> !Maybe Token
- Language.Fortran.Lexer.FreeForm: [aiPreviousTokensInLine] :: AlexInput -> ![Token]
- Language.Fortran.Lexer.FreeForm: [aiSourceBytes] :: AlexInput -> !ByteString
- Language.Fortran.Lexer.FreeForm: [aiStartCode] :: AlexInput -> {-# UNPACK #-} !StartCode
- Language.Fortran.Lexer.FreeForm: [lexemeEnd] :: Lexeme -> {-# UNPACK #-} !Position
- Language.Fortran.Lexer.FreeForm: [lexemeIsCmt] :: Lexeme -> !Bool
- Language.Fortran.Lexer.FreeForm: [lexemeMatch] :: Lexeme -> !String
- Language.Fortran.Lexer.FreeForm: [lexemeStart] :: Lexeme -> {-# UNPACK #-} !Position
- Language.Fortran.Lexer.FreeForm: [scActual] :: StartCode -> {-# UNPACK #-} !Int
- Language.Fortran.Lexer.FreeForm: [scStatus] :: StartCode -> !StartCodeStatus
- Language.Fortran.Lexer.FreeForm: addSpan :: (SrcSpan -> Token) -> LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: addSpanAndMatch :: (SrcSpan -> String -> Token) -> LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: addToPreviousTokensInLine :: Token -> LexAction ()
- Language.Fortran.Lexer.FreeForm: adjustComment :: LexAction (Maybe Token) -> LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: advance :: Move -> Position -> Position
- Language.Fortran.Lexer.FreeForm: advanceWithoutContinuation :: AlexInput -> Maybe AlexInput
- Language.Fortran.Lexer.FreeForm: alexAndPred :: (t1 -> t2 -> t3 -> t4 -> Bool) -> (t1 -> t2 -> t3 -> t4 -> Bool) -> t1 -> t2 -> t3 -> t4 -> Bool
- Language.Fortran.Lexer.FreeForm: alexGetByte :: AlexInput -> Maybe (Word8, AlexInput)
- Language.Fortran.Lexer.FreeForm: alexIndexInt16OffAddr :: AlexAddr -> Int# -> Int#
- Language.Fortran.Lexer.FreeForm: alexIndexInt32OffAddr :: AlexAddr -> Int# -> Int#
- Language.Fortran.Lexer.FreeForm: alexInputPrevChar :: AlexInput -> Char
- Language.Fortran.Lexer.FreeForm: alexPrevCharIs :: Char -> p1 -> AlexInput -> p2 -> p3 -> Bool
- Language.Fortran.Lexer.FreeForm: alexPrevCharIsOneOf :: Array Char e -> p1 -> AlexInput -> p2 -> p3 -> e
- Language.Fortran.Lexer.FreeForm: alexPrevCharMatches :: (Char -> t) -> p1 -> AlexInput -> p2 -> p3 -> t
- Language.Fortran.Lexer.FreeForm: alexRightContext :: Int -> AlexAccPred User
- Language.Fortran.Lexer.FreeForm: alexScan :: AlexInput -> Int -> AlexReturn (LexAction (Maybe Token))
- Language.Fortran.Lexer.FreeForm: alexScanUser :: User -> AlexInput -> Int -> AlexReturn (LexAction (Maybe Token))
- Language.Fortran.Lexer.FreeForm: alex_accept :: Array Int (AlexAcc User)
- Language.Fortran.Lexer.FreeForm: alex_action_0 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_1 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_10 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_100 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_101 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_102 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_103 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_104 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_105 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_106 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_107 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_108 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_109 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_11 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_110 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_111 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_112 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_113 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_114 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_115 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_116 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_117 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_118 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_119 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_12 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_120 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_121 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_122 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_123 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_124 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_125 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_126 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_127 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_128 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_129 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_13 :: Parse AlexInput Token (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_130 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_131 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_132 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_133 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_134 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_135 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_136 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_137 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_138 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_139 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_14 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_140 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_141 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_142 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_143 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_144 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_145 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_146 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_147 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_148 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_149 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_15 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_150 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_151 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_152 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_153 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_154 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_155 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_156 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_157 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_158 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_159 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_16 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_160 :: Parse AlexInput Token (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_161 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_162 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_163 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_164 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_165 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_166 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_167 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_168 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_169 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_17 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_170 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_171 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_172 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_173 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_174 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_175 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_176 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_177 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_178 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_179 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_18 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_180 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_181 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_182 :: Parse AlexInput Token (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_183 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_184 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_185 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_186 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_187 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_188 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_189 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_19 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_190 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_191 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_192 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_193 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_194 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_195 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_196 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_197 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_198 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_199 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_2 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_20 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_200 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_201 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_202 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_203 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_204 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_205 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_206 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_207 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_208 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_21 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_22 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_23 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_24 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_25 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_26 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_27 :: Parse AlexInput Token (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_28 :: Parse AlexInput Token (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_29 :: Parse AlexInput Token (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_3 :: Parse AlexInput Token (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_30 :: Parse AlexInput Token (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_31 :: Parse AlexInput Token (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_32 :: Parse AlexInput Token (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_33 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_34 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_35 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_36 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_37 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_38 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_39 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_40 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_41 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_42 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_43 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_44 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_45 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_46 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_47 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_48 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_49 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_5 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_50 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_51 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_52 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_53 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_54 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_55 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_56 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_57 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_58 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_59 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_6 :: Parse AlexInput Token (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_60 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_61 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_62 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_63 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_64 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_65 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_66 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_67 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_68 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_69 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_7 :: Parse AlexInput Token (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_70 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_71 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_72 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_73 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_74 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_75 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_76 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_77 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_78 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_79 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_8 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_80 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_81 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_82 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_83 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_84 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_85 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_86 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_87 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_88 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_89 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_9 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_90 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_91 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_92 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_93 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_94 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_95 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_96 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_97 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_98 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_action_99 :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: alex_actions :: Array Int (LexAction (Maybe Token))
- Language.Fortran.Lexer.FreeForm: alex_base :: AlexAddr
- Language.Fortran.Lexer.FreeForm: alex_check :: AlexAddr
- Language.Fortran.Lexer.FreeForm: alex_deflt :: AlexAddr
- Language.Fortran.Lexer.FreeForm: alex_scan_tkn :: User -> AlexInput -> Int# -> AlexInput -> Int# -> AlexLastAcc -> (AlexLastAcc, AlexInput)
- Language.Fortran.Lexer.FreeForm: alex_tab_size :: Int
- Language.Fortran.Lexer.FreeForm: alex_table :: AlexAddr
- Language.Fortran.Lexer.FreeForm: allocateP :: User -> AlexInput -> Int -> AlexInput -> Bool
- Language.Fortran.Lexer.FreeForm: assignStP :: User -> AlexInput -> Int -> AlexInput -> Bool
- Language.Fortran.Lexer.FreeForm: attributeP :: User -> AlexInput -> Int -> AlexInput -> Bool
- Language.Fortran.Lexer.FreeForm: bindP :: User -> AlexInput -> Int -> AlexInput -> Bool
- Language.Fortran.Lexer.FreeForm: caseStP :: User -> AlexInput -> Int -> AlexInput -> Bool
- Language.Fortran.Lexer.FreeForm: checkPreviousTokensInLine :: (Token -> Bool) -> AlexInput -> Bool
- Language.Fortran.Lexer.FreeForm: class SpecifiesType a
- Language.Fortran.Lexer.FreeForm: collectFreeTokens :: FortranVersion -> ByteString -> [Token]
- Language.Fortran.Lexer.FreeForm: comma :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: constructNameP :: User -> AlexInput -> Int -> AlexInput -> Bool
- Language.Fortran.Lexer.FreeForm: currentChar :: AlexInput -> Char
- Language.Fortran.Lexer.FreeForm: data AlexAcc user
- Language.Fortran.Lexer.FreeForm: data AlexAddr
- Language.Fortran.Lexer.FreeForm: data AlexInput
- Language.Fortran.Lexer.FreeForm: data AlexLastAcc
- Language.Fortran.Lexer.FreeForm: data AlexReturn a
- Language.Fortran.Lexer.FreeForm: data Lexeme
- Language.Fortran.Lexer.FreeForm: data Move
- Language.Fortran.Lexer.FreeForm: data StartCode
- Language.Fortran.Lexer.FreeForm: data StartCodeStatus
- Language.Fortran.Lexer.FreeForm: data Token
- Language.Fortran.Lexer.FreeForm: data User
- Language.Fortran.Lexer.FreeForm: fillConstr :: (a -> Token) -> Constr
- Language.Fortran.Lexer.FreeForm: followsBindP :: User -> AlexInput -> Int -> AlexInput -> Bool
- Language.Fortran.Lexer.FreeForm: followsCP :: User -> AlexInput -> Int -> AlexInput -> Bool
- Language.Fortran.Lexer.FreeForm: followsColonP :: User -> AlexInput -> Int -> AlexInput -> Bool
- Language.Fortran.Lexer.FreeForm: followsDoWithOptLabelP :: User -> AlexInput -> Int -> AlexInput -> Bool
- Language.Fortran.Lexer.FreeForm: followsFlushP :: User -> AlexInput -> Int -> AlexInput -> Bool
- Language.Fortran.Lexer.FreeForm: followsIntentP :: User -> AlexInput -> Int -> AlexInput -> Bool
- Language.Fortran.Lexer.FreeForm: followsProcedureP :: User -> AlexInput -> Int -> AlexInput -> Bool
- Language.Fortran.Lexer.FreeForm: formatP :: User -> AlexInput -> Int -> AlexInput -> Bool
- Language.Fortran.Lexer.FreeForm: genericSpecP :: User -> AlexInput -> Int -> AlexInput -> Bool
- Language.Fortran.Lexer.FreeForm: getLexeme :: LexAction Lexeme
- Language.Fortran.Lexer.FreeForm: getLexemeSpan :: LexAction SrcSpan
- Language.Fortran.Lexer.FreeForm: getMatch :: LexAction String
- Language.Fortran.Lexer.FreeForm: ifConditionEndP :: User -> AlexInput -> Int -> AlexInput -> Bool
- Language.Fortran.Lexer.FreeForm: initLexeme :: Lexeme
- Language.Fortran.Lexer.FreeForm: initParseState :: ByteString -> FortranVersion -> String -> ParseState AlexInput
- Language.Fortran.Lexer.FreeForm: instance Data.Data.Data Language.Fortran.Lexer.FreeForm.Token
- Language.Fortran.Lexer.FreeForm: instance GHC.Classes.Eq Language.Fortran.Lexer.FreeForm.Token
- Language.Fortran.Lexer.FreeForm: instance GHC.Generics.Generic Language.Fortran.Lexer.FreeForm.Token
- Language.Fortran.Lexer.FreeForm: instance GHC.Show.Show Language.Fortran.Lexer.FreeForm.AlexInput
- Language.Fortran.Lexer.FreeForm: instance GHC.Show.Show Language.Fortran.Lexer.FreeForm.Lexeme
- Language.Fortran.Lexer.FreeForm: instance GHC.Show.Show Language.Fortran.Lexer.FreeForm.StartCode
- Language.Fortran.Lexer.FreeForm: instance GHC.Show.Show Language.Fortran.Lexer.FreeForm.StartCodeStatus
- Language.Fortran.Lexer.FreeForm: instance GHC.Show.Show Language.Fortran.Lexer.FreeForm.Token
- Language.Fortran.Lexer.FreeForm: instance Language.Fortran.Lexer.FreeForm.SpecifiesType Language.Fortran.Lexer.FreeForm.Token
- Language.Fortran.Lexer.FreeForm: instance Language.Fortran.Lexer.FreeForm.SpecifiesType [Language.Fortran.Lexer.FreeForm.Token]
- Language.Fortran.Lexer.FreeForm: instance Language.Fortran.ParserMonad.LastToken Language.Fortran.Lexer.FreeForm.AlexInput Language.Fortran.Lexer.FreeForm.Token
- Language.Fortran.Lexer.FreeForm: instance Language.Fortran.ParserMonad.Tok Language.Fortran.Lexer.FreeForm.Token
- Language.Fortran.Lexer.FreeForm: instance Language.Fortran.Util.FirstParameter.FirstParameter Language.Fortran.Lexer.FreeForm.Token Language.Fortran.Util.Position.SrcSpan
- Language.Fortran.Lexer.FreeForm: instance Language.Fortran.Util.FirstParameter.FirstParameter Language.Fortran.Lexer.FreeForm.Token Language.Fortran.Util.Position.SrcSpan => Language.Fortran.Util.Position.Spanned Language.Fortran.Lexer.FreeForm.Token
- Language.Fortran.Lexer.FreeForm: instance Language.Fortran.Util.Position.Loc Language.Fortran.Lexer.FreeForm.AlexInput
- Language.Fortran.Lexer.FreeForm: instance Language.Fortran.Util.Position.Spanned Language.Fortran.Lexer.FreeForm.Lexeme
- Language.Fortran.Lexer.FreeForm: invalidPosition :: Position
- Language.Fortran.Lexer.FreeForm: isContinuation :: AlexInput -> Bool
- Language.Fortran.Lexer.FreeForm: isTypeSpec :: SpecifiesType a => a -> Bool
- Language.Fortran.Lexer.FreeForm: isValidPosition :: Position -> Bool
- Language.Fortran.Lexer.FreeForm: labelledWhereP :: User -> AlexInput -> Int -> AlexInput -> Bool
- Language.Fortran.Lexer.FreeForm: leftPar :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: lexCharacter :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: lexHash :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: lexer :: (Token -> LexAction a) -> LexAction a
- Language.Fortran.Lexer.FreeForm: lexer' :: LexAction Token
- Language.Fortran.Lexer.FreeForm: nextTokenConstr :: User -> AlexInput -> Maybe Constr
- Language.Fortran.Lexer.FreeForm: normaliseStartCode :: LexAction ()
- Language.Fortran.Lexer.FreeForm: notDefinedOperP :: User -> AlexInput -> Int -> AlexInput -> Bool
- Language.Fortran.Lexer.FreeForm: notPrecedingDotP :: User -> AlexInput -> Int -> AlexInput -> Bool
- Language.Fortran.Lexer.FreeForm: opP :: User -> AlexInput -> Int -> AlexInput -> Bool
- Language.Fortran.Lexer.FreeForm: parenLevel :: [Token] -> Int
- Language.Fortran.Lexer.FreeForm: partOfExpOrPointerAssignmentP :: User -> AlexInput -> Int -> AlexInput -> Bool
- Language.Fortran.Lexer.FreeForm: precedesDoubleColon :: AlexInput -> Bool
- Language.Fortran.Lexer.FreeForm: prevTokenConstr :: AlexInput -> Maybe Constr
- Language.Fortran.Lexer.FreeForm: putLexeme :: Lexeme -> LexAction ()
- Language.Fortran.Lexer.FreeForm: putMatch :: String -> LexAction ()
- Language.Fortran.Lexer.FreeForm: quickIndex :: Array Int (AlexAcc User) -> Int -> AlexAcc User
- Language.Fortran.Lexer.FreeForm: resetLexeme :: LexAction ()
- Language.Fortran.Lexer.FreeForm: resultP :: User -> AlexInput -> Int -> AlexInput -> Bool
- Language.Fortran.Lexer.FreeForm: scC :: Int
- Language.Fortran.Lexer.FreeForm: scI :: Int
- Language.Fortran.Lexer.FreeForm: scN :: Int
- Language.Fortran.Lexer.FreeForm: scT :: Int
- Language.Fortran.Lexer.FreeForm: seenConstr :: Constr -> AlexInput -> Bool
- Language.Fortran.Lexer.FreeForm: selectorP :: User -> AlexInput -> Int -> AlexInput -> Bool
- Language.Fortran.Lexer.FreeForm: skipCComment :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: skipContinuation :: AlexInput -> AlexInput
- Language.Fortran.Lexer.FreeForm: slashOrDivision :: LexAction (Maybe Token)
- Language.Fortran.Lexer.FreeForm: stabiliseStartCode :: LexAction ()
- Language.Fortran.Lexer.FreeForm: toSC :: Int -> LexAction ()
- Language.Fortran.Lexer.FreeForm: type AlexAccPred user = user -> AlexInput -> Int -> AlexInput -> Bool
- Language.Fortran.Lexer.FreeForm: type LexAction a = Parse AlexInput Token a
- Language.Fortran.Lexer.FreeForm: typeSpecP :: User -> AlexInput -> Int -> AlexInput -> Bool
- Language.Fortran.Lexer.FreeForm: updateLexeme :: Char -> Position -> AlexInput -> AlexInput
- Language.Fortran.Lexer.FreeForm: updatePreviousToken :: Maybe Token -> LexAction ()
- Language.Fortran.Lexer.FreeForm: useStP :: User -> AlexInput -> Int -> AlexInput -> Bool
- Language.Fortran.Lexer.FreeForm: vanillaAlexInput :: AlexInput
- Language.Fortran.Parser.Any: fortranParser :: Parser
- Language.Fortran.Parser.Any: fortranParserWithModFiles :: ParserWithModFiles
- Language.Fortran.Parser.Any: fortranParserWithModFilesAndVersion :: FortranVersion -> ParserWithModFiles
- Language.Fortran.Parser.Any: fortranParserWithVersion :: FortranVersion -> Parser
- Language.Fortran.Parser.Any: parserVersions :: FortranVersion -> Parser
- Language.Fortran.Parser.Any: parserWithModFilesVersions :: FortranVersion -> ParserWithModFiles
- Language.Fortran.Parser.Any: type Parser = ByteString -> String -> Either ParseErrorSimple (ProgramFile A0)
- Language.Fortran.Parser.Any: type ParserWithModFiles = ModFiles -> ByteString -> String -> Either ParseErrorSimple (ProgramFile A0)
- Language.Fortran.Parser.Fortran2003: blockParser :: LexAction (Block A0)
- Language.Fortran.Parser.Fortran2003: fortran2003Parser :: ByteString -> String -> ParseResult AlexInput Token (ProgramFile A0)
- Language.Fortran.Parser.Fortran2003: fortran2003ParserWithModFiles :: ModFiles -> ByteString -> String -> ParseResult AlexInput Token (ProgramFile A0)
- 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.Fortran2003: functionParser :: LexAction (ProgramUnit A0)
- Language.Fortran.Parser.Fortran2003: statementParser :: LexAction (Statement A0)
- Language.Fortran.Parser.Fortran66: expressionParser :: LexAction (Expression A0)
- Language.Fortran.Parser.Fortran66: fortran66Parser :: ByteString -> String -> ParseResult AlexInput Token (ProgramFile A0)
- Language.Fortran.Parser.Fortran66: fortran66ParserWithModFiles :: ModFiles -> 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.Fortran66: statementParser :: LexAction (Statement A0)
- Language.Fortran.Parser.Fortran77: blockParser :: LexAction (Block A0)
- Language.Fortran.Parser.Fortran77: expressionParser :: LexAction (Expression A0)
- Language.Fortran.Parser.Fortran77: extended77Parser :: ByteString -> String -> ParseResult AlexInput Token (ProgramFile A0)
- Language.Fortran.Parser.Fortran77: extended77ParserWithModFiles :: ModFiles -> 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: fortran77Parser :: ByteString -> String -> ParseResult AlexInput Token (ProgramFile A0)
- Language.Fortran.Parser.Fortran77: fortran77ParserWithModFiles :: ModFiles -> 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: includeParser :: FortranVersion -> ByteString -> String -> ParseResult AlexInput Token [Block A0]
- Language.Fortran.Parser.Fortran77: legacy77Parser :: ByteString -> String -> ParseResult AlexInput Token (ProgramFile A0)
- Language.Fortran.Parser.Fortran77: legacy77ParserWithIncludes :: [String] -> ByteString -> String -> IO (ParseResult AlexInput Token (ProgramFile A0))
- Language.Fortran.Parser.Fortran77: legacy77ParserWithIncludesWithTransforms :: [Transformation] -> [String] -> ByteString -> String -> IO (ParseResult AlexInput Token (ProgramFile A0))
- Language.Fortran.Parser.Fortran77: legacy77ParserWithModFiles :: ModFiles -> ByteString -> String -> 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.Fortran77: statementParser :: LexAction (Statement A0)
- Language.Fortran.Parser.Fortran90: blockParser :: LexAction (Block A0)
- Language.Fortran.Parser.Fortran90: fortran90Parser :: ByteString -> String -> ParseResult AlexInput Token (ProgramFile A0)
- Language.Fortran.Parser.Fortran90: fortran90ParserWithModFiles :: ModFiles -> 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.Fortran90: functionParser :: LexAction (ProgramUnit A0)
- Language.Fortran.Parser.Fortran90: statementParser :: LexAction (Statement A0)
- Language.Fortran.Parser.Fortran95: blockParser :: LexAction (Block A0)
- Language.Fortran.Parser.Fortran95: fortran95Parser :: ByteString -> String -> ParseResult AlexInput Token (ProgramFile A0)
- Language.Fortran.Parser.Fortran95: fortran95ParserWithModFiles :: ModFiles -> 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.Parser.Fortran95: functionParser :: LexAction (ProgramUnit A0)
- Language.Fortran.Parser.Fortran95: statementParser :: LexAction (Statement A0)
- Language.Fortran.Parser.Utils: readInteger :: String -> Maybe Integer
- Language.Fortran.Parser.Utils: readReal :: String -> Maybe Double
- Language.Fortran.ParserMonad: ConCommon :: Context
- Language.Fortran.ParserMonad: ConData :: Context
- Language.Fortran.ParserMonad: ConImplicit :: Context
- Language.Fortran.ParserMonad: ConNamelist :: Context
- Language.Fortran.ParserMonad: ConStart :: Context
- Language.Fortran.ParserMonad: ParanthesesCount :: Integer -> Bool -> ParanthesesCount
- Language.Fortran.ParserMonad: Parse :: (ParseState b -> ParseResult b c a) -> Parse b c a
- Language.Fortran.ParserMonad: ParseError :: Position -> Maybe b -> String -> String -> ParseError a b
- Language.Fortran.ParserMonad: ParseErrorSimple :: Position -> String -> String -> ParseErrorSimple
- Language.Fortran.ParserMonad: ParseFailed :: ParseError b c -> ParseResult b c a
- Language.Fortran.ParserMonad: ParseOk :: a -> ParseState b -> ParseResult b c a
- Language.Fortran.ParserMonad: ParseState :: a -> ParanthesesCount -> FortranVersion -> String -> [Context] -> ParseState a
- Language.Fortran.ParserMonad: [errFilename] :: ParseError a b -> String
- Language.Fortran.ParserMonad: [errLastToken] :: ParseError a b -> Maybe b
- Language.Fortran.ParserMonad: [errMsg] :: ParseError a b -> String
- Language.Fortran.ParserMonad: [errPos] :: ParseError a b -> Position
- Language.Fortran.ParserMonad: [errorFilename] :: ParseErrorSimple -> String
- Language.Fortran.ParserMonad: [errorMsg] :: ParseErrorSimple -> String
- Language.Fortran.ParserMonad: [errorPos] :: ParseErrorSimple -> Position
- Language.Fortran.ParserMonad: [pcActual] :: ParanthesesCount -> Integer
- Language.Fortran.ParserMonad: [pcHasReached0] :: ParanthesesCount -> Bool
- Language.Fortran.ParserMonad: [psAlexInput] :: ParseState a -> a
- Language.Fortran.ParserMonad: [psContext] :: ParseState a -> [Context]
- Language.Fortran.ParserMonad: [psFilename] :: ParseState a -> String
- Language.Fortran.ParserMonad: [psParanthesesCount] :: ParseState a -> ParanthesesCount
- Language.Fortran.ParserMonad: [psVersion] :: ParseState a -> FortranVersion
- Language.Fortran.ParserMonad: [unParse] :: Parse b c a -> ParseState b -> ParseResult b c a
- Language.Fortran.ParserMonad: class LastToken a b | a -> b
- Language.Fortran.ParserMonad: class Tok a
- Language.Fortran.ParserMonad: collectTokens :: forall a b. (Loc b, Tok a, LastToken b a, Show a) => Parse b a a -> ParseState b -> [a]
- Language.Fortran.ParserMonad: collectTokensSafe :: forall a b. (Loc b, Tok a, LastToken b a, Show a) => Parse b a a -> ParseState b -> Maybe [a]
- Language.Fortran.ParserMonad: data Context
- Language.Fortran.ParserMonad: data ParanthesesCount
- Language.Fortran.ParserMonad: data ParseError a b
- Language.Fortran.ParserMonad: data ParseErrorSimple
- Language.Fortran.ParserMonad: data ParseResult b c a
- Language.Fortran.ParserMonad: data ParseState a
- Language.Fortran.ParserMonad: decPar :: (Loc a, LastToken a b, Show b) => Parse a b ()
- Language.Fortran.ParserMonad: eofToken :: Tok a => a -> Bool
- Language.Fortran.ParserMonad: evalParse :: (Loc b, LastToken b c, Show c) => Parse b c a -> ParseState b -> a
- Language.Fortran.ParserMonad: execParse :: (Loc b, LastToken b c, Show c) => Parse b c a -> ParseState b -> ParseState b
- Language.Fortran.ParserMonad: fromParseResult :: Show c => ParseResult b c a -> Either ParseErrorSimple a
- Language.Fortran.ParserMonad: fromParseResultUnsafe :: Show c => ParseResult b c a -> a
- Language.Fortran.ParserMonad: fromRight :: Show a => Either a b -> b
- Language.Fortran.ParserMonad: getAlex :: (Loc a, LastToken a b, Show b) => Parse a b a
- Language.Fortran.ParserMonad: getLastToken :: (LastToken a b, Show b) => a -> Maybe b
- Language.Fortran.ParserMonad: getParanthesesCount :: (Loc a, LastToken a b, Show b) => Parse a b ParanthesesCount
- Language.Fortran.ParserMonad: getPosition :: (Loc a, LastToken a b, Show b) => Parse a b Position
- Language.Fortran.ParserMonad: getSrcSpan :: (Loc a, LastToken a b, Show b) => Position -> Parse a b SrcSpan
- Language.Fortran.ParserMonad: getVersion :: (Loc a, LastToken a b, Show b) => Parse a b FortranVersion
- Language.Fortran.ParserMonad: incPar :: (Loc a, LastToken a b, Show b) => Parse a b ()
- Language.Fortran.ParserMonad: instance (Data.Typeable.Internal.Typeable a, Data.Typeable.Internal.Typeable b, GHC.Show.Show a, GHC.Show.Show b) => GHC.Exception.Type.Exception (Language.Fortran.ParserMonad.ParseError a b)
- Language.Fortran.ParserMonad: instance (Language.Fortran.Util.Position.Loc b, Language.Fortran.ParserMonad.LastToken b c, GHC.Show.Show c) => Control.Monad.Error.Class.MonadError (Language.Fortran.ParserMonad.ParseError b c) (Language.Fortran.ParserMonad.Parse b c)
- Language.Fortran.ParserMonad: instance (Language.Fortran.Util.Position.Loc b, Language.Fortran.ParserMonad.LastToken b c, GHC.Show.Show c) => Control.Monad.Fail.MonadFail (Language.Fortran.ParserMonad.Parse b c)
- Language.Fortran.ParserMonad: instance (Language.Fortran.Util.Position.Loc b, Language.Fortran.ParserMonad.LastToken b c, GHC.Show.Show c) => Control.Monad.State.Class.MonadState (Language.Fortran.ParserMonad.ParseState b) (Language.Fortran.ParserMonad.Parse b c)
- Language.Fortran.ParserMonad: instance (Language.Fortran.Util.Position.Loc b, Language.Fortran.ParserMonad.LastToken b c, GHC.Show.Show c) => GHC.Base.Applicative (Language.Fortran.ParserMonad.Parse b c)
- Language.Fortran.ParserMonad: instance (Language.Fortran.Util.Position.Loc b, Language.Fortran.ParserMonad.LastToken b c, GHC.Show.Show c) => GHC.Base.Functor (Language.Fortran.ParserMonad.Parse b c)
- Language.Fortran.ParserMonad: instance (Language.Fortran.Util.Position.Loc b, Language.Fortran.ParserMonad.LastToken b c, GHC.Show.Show c) => GHC.Base.Monad (Language.Fortran.ParserMonad.Parse b c)
- Language.Fortran.ParserMonad: instance GHC.Base.Functor (Language.Fortran.ParserMonad.ParseResult b c)
- Language.Fortran.ParserMonad: instance GHC.Classes.Eq Language.Fortran.ParserMonad.Context
- Language.Fortran.ParserMonad: instance GHC.Classes.Eq Language.Fortran.ParserMonad.ParanthesesCount
- Language.Fortran.ParserMonad: instance GHC.Show.Show Language.Fortran.ParserMonad.Context
- Language.Fortran.ParserMonad: instance GHC.Show.Show Language.Fortran.ParserMonad.ParanthesesCount
- Language.Fortran.ParserMonad: instance GHC.Show.Show Language.Fortran.ParserMonad.ParseErrorSimple
- Language.Fortran.ParserMonad: instance GHC.Show.Show a => GHC.Show.Show (Language.Fortran.ParserMonad.ParseState a)
- Language.Fortran.ParserMonad: instance GHC.Show.Show b => GHC.Show.Show (Language.Fortran.ParserMonad.ParseError a b)
- Language.Fortran.ParserMonad: newtype Parse b c a
- Language.Fortran.ParserMonad: popContext :: (Loc a, LastToken a b, Show b) => Parse a b ()
- Language.Fortran.ParserMonad: pushContext :: (Loc a, LastToken a b, Show b) => Context -> Parse a b ()
- Language.Fortran.ParserMonad: putAlex :: (Loc a, LastToken a b, Show b) => a -> Parse a b ()
- Language.Fortran.ParserMonad: resetPar :: (Loc a, LastToken a b, Show b) => Parse a b ()
- Language.Fortran.ParserMonad: runParse :: (Loc b, LastToken b c, Show c) => Parse b c a -> ParseState b -> ParseResult b c a
- Language.Fortran.ParserMonad: runParseUnsafe :: (Loc b, LastToken b c, Show c) => Parse b c a -> ParseState b -> (a, ParseState b)
- Language.Fortran.ParserMonad: throwIOerror :: String -> a
- Language.Fortran.ParserMonad: tokenMsg :: Show a => Maybe a -> String
- Language.Fortran.ParserMonad: topContext :: (Loc a, LastToken a b, Show b) => Parse a b Context
- Language.Fortran.Transformation.TransformMonad: getProgramFile :: Transform a (ProgramFile (Analysis a))
- Language.Fortran.Transformation.TransformMonad: modifyProgramFile :: (ProgramFile (Analysis a) -> ProgramFile (Analysis a)) -> Transform a ()
- Language.Fortran.Transformation.TransformMonad: putProgramFile :: ProgramFile (Analysis a) -> Transform a ()
- Language.Fortran.Transformation.TransformMonad: runTransform :: Data a => TypeEnv -> ModuleMap -> Transform a () -> ProgramFile a -> ProgramFile a
- Language.Fortran.Transformation.TransformMonad: type Transform a = State (TransformationState a)
- Language.Fortran.Transformer: DisambiguateFunction :: Transformation
- Language.Fortran.Transformer: DisambiguateIntrinsic :: Transformation
- Language.Fortran.Transformer: GroupDo :: Transformation
- Language.Fortran.Transformer: GroupForall :: Transformation
- Language.Fortran.Transformer: GroupLabeledDo :: Transformation
- Language.Fortran.Transformer: data Transformation
- Language.Fortran.Transformer: defaultTransformations :: FortranVersion -> [Transformation]
- Language.Fortran.Transformer: instance GHC.Classes.Eq Language.Fortran.Transformer.Transformation
- Language.Fortran.Transformer: transform :: Data a => [Transformation] -> ProgramFile a -> ProgramFile a
- Language.Fortran.Transformer: transformWithModFiles :: Data a => ModFiles -> [Transformation] -> ProgramFile a -> ProgramFile a
- Language.Fortran.Util.FirstParameter: instance (Language.Fortran.Util.FirstParameter.GFirstParameter a e, Language.Fortran.Util.FirstParameter.GFirstParameter b e) => Language.Fortran.Util.FirstParameter.GFirstParameter (a GHC.Generics.:*: b) e
- Language.Fortran.Util.FirstParameter: instance (Language.Fortran.Util.FirstParameter.GFirstParameter a e, Language.Fortran.Util.FirstParameter.GFirstParameter b e) => Language.Fortran.Util.FirstParameter.GFirstParameter (a GHC.Generics.:+: b) e
- Language.Fortran.Util.FirstParameter: instance Language.Fortran.Util.FirstParameter.GFirstParameter a e => Language.Fortran.Util.FirstParameter.GFirstParameter (GHC.Generics.M1 i c a) e
- Language.Fortran.Util.SecondParameter: instance (Language.Fortran.Util.SecondParameter.GSecondParameter a e, Language.Fortran.Util.SecondParameter.GSecondParameter b e) => Language.Fortran.Util.SecondParameter.GSecondParameter (a GHC.Generics.:+: b) e
- Language.Fortran.Util.SecondParameter: instance (Language.Fortran.Util.SecondParameter.ParameterLeaf a, Language.Fortran.Util.SecondParameter.GSecondParameter a e, Language.Fortran.Util.SecondParameter.GSecondParameter' b e) => Language.Fortran.Util.SecondParameter.GSecondParameter (a GHC.Generics.:*: b) e
- Language.Fortran.Util.SecondParameter: instance Language.Fortran.Util.SecondParameter.GSecondParameter a e => Language.Fortran.Util.SecondParameter.GSecondParameter (GHC.Generics.M1 i c a) e
- Language.Fortran.Util.SecondParameter: instance Language.Fortran.Util.SecondParameter.GSecondParameter' a e => Language.Fortran.Util.SecondParameter.GSecondParameter' (GHC.Generics.M1 i c a) e
- Language.Fortran.Util.SecondParameter: instance Language.Fortran.Util.SecondParameter.GSecondParameter' a e => Language.Fortran.Util.SecondParameter.GSecondParameter' (a GHC.Generics.:*: b) e
- Language.Fortran.Util.SecondParameter: instance Language.Fortran.Util.SecondParameter.ParameterLeaf (GHC.Generics.M1 i c a)
- Language.Fortran.Util.SecondParameter: instance Language.Fortran.Util.SecondParameter.ParameterLeaf (a GHC.Generics.:*: b)
- Language.Fortran.Version: deduceVersion :: FilePath -> FortranVersion
+ Language.Fortran.AST: ArgExpr :: Expression a -> ArgumentExpression a
+ Language.Fortran.AST: ArgExprVar :: a -> SrcSpan -> Name -> ArgumentExpression a
+ Language.Fortran.AST: argExprNormalize :: ArgumentExpression a -> Expression a
+ Language.Fortran.AST: argExtractExpr :: Argument a -> Expression a
+ Language.Fortran.AST: data ArgumentExpression a
+ Language.Fortran.AST: instance Control.DeepSeq.NFData a => Control.DeepSeq.NFData (Language.Fortran.AST.ArgumentExpression a)
+ Language.Fortran.AST: instance Data.Data.Data a => Data.Data.Data (Language.Fortran.AST.ArgumentExpression a)
+ Language.Fortran.AST: instance GHC.Base.Functor Language.Fortran.AST.ArgumentExpression
+ Language.Fortran.AST: instance GHC.Classes.Eq a => GHC.Classes.Eq (Language.Fortran.AST.ArgumentExpression a)
+ Language.Fortran.AST: instance GHC.Generics.Generic (Language.Fortran.AST.ArgumentExpression a)
+ Language.Fortran.AST: instance GHC.Show.Show a => GHC.Show.Show (Language.Fortran.AST.ArgumentExpression a)
+ Language.Fortran.AST: instance Text.PrettyPrint.GenericPretty.Out a => Text.PrettyPrint.GenericPretty.Out (Language.Fortran.AST.ArgumentExpression a)
+ Language.Fortran.AST: instance forall k (a :: k). (Data.Typeable.Internal.Typeable a, Data.Typeable.Internal.Typeable k) => Data.Data.Data (Language.Fortran.AST.Comment a)
+ Language.Fortran.AST: instance forall k (a :: k). GHC.Classes.Eq (Language.Fortran.AST.Comment a)
+ Language.Fortran.AST: instance forall k (a :: k). GHC.Generics.Generic (Language.Fortran.AST.Comment a)
+ Language.Fortran.AST: instance forall k (a :: k). GHC.Show.Show (Language.Fortran.AST.Comment a)
+ Language.Fortran.Parser: byVer :: FortranVersion -> Parser (ProgramFile A0)
+ Language.Fortran.Parser: byVerWithMods :: ModFiles -> FortranVersion -> Parser (ProgramFile A0)
+ Language.Fortran.Parser: collectTokens :: forall a b. (Loc b, Tok a, LastToken b a, Show a) => Parse b a a -> ParseState b -> [a]
+ Language.Fortran.Parser: collectTokensSafe :: forall a b. (Loc b, Tok a, LastToken b a, Show a) => Parse b a a -> ParseState b -> Maybe [a]
+ Language.Fortran.Parser: defaultTransformation :: Data a => FortranVersion -> Transform a ()
+ Language.Fortran.Parser: f2003 :: Parser (ProgramFile A0)
+ Language.Fortran.Parser: f2003NoTransform :: Parser (ProgramFile A0)
+ Language.Fortran.Parser: f66 :: Parser (ProgramFile A0)
+ Language.Fortran.Parser: f66NoTransform :: Parser (ProgramFile A0)
+ Language.Fortran.Parser: f77 :: Parser (ProgramFile A0)
+ Language.Fortran.Parser: f77NoTransform :: Parser (ProgramFile A0)
+ Language.Fortran.Parser: f77e :: Parser (ProgramFile A0)
+ Language.Fortran.Parser: f77eNoTransform :: Parser (ProgramFile A0)
+ Language.Fortran.Parser: f77l :: Parser (ProgramFile A0)
+ Language.Fortran.Parser: f77lIncludes :: [FilePath] -> ModFiles -> String -> ByteString -> IO (ProgramFile A0)
+ Language.Fortran.Parser: f77lNoTransform :: Parser (ProgramFile A0)
+ Language.Fortran.Parser: f90 :: Parser (ProgramFile A0)
+ Language.Fortran.Parser: f90Expr :: Parser (Expression A0)
+ Language.Fortran.Parser: f90NoTransform :: Parser (ProgramFile A0)
+ Language.Fortran.Parser: f95 :: Parser (ProgramFile A0)
+ Language.Fortran.Parser: f95NoTransform :: Parser (ProgramFile A0)
+ Language.Fortran.Parser: initParseStateFixed :: StateInit AlexInput
+ Language.Fortran.Parser: initParseStateFixedExpr :: StateInit AlexInput
+ Language.Fortran.Parser: initParseStateFree :: StateInit AlexInput
+ Language.Fortran.Parser: initParseStateFreeExpr :: StateInit AlexInput
+ Language.Fortran.Parser: makeParser :: (Loc ai, LastToken ai tok, Show tok) => StateInit ai -> ParserMaker ai tok a
+ Language.Fortran.Parser: makeParserFixed :: ParserMaker AlexInput Token a
+ Language.Fortran.Parser: makeParserFree :: ParserMaker AlexInput Token a
+ Language.Fortran.Parser: parseUnsafe :: Parser a -> ByteString -> a
+ Language.Fortran.Parser: transformAs :: Data a => FortranVersion -> Parser (ProgramFile a) -> ModFiles -> Parser (ProgramFile a)
+ Language.Fortran.Parser: type Parser a = String -> ByteString -> Either ParseErrorSimple a
+ Language.Fortran.Parser: type ParserMaker ai tok a = Parse ai tok a -> FortranVersion -> Parser a
+ Language.Fortran.Parser: type StateInit s = String -> FortranVersion -> ByteString -> ParseState s
+ Language.Fortran.Parser.Fixed.Fortran66: blockParser :: LexAction (Block A0)
+ Language.Fortran.Parser.Fixed.Fortran66: expressionParser :: LexAction (Expression A0)
+ Language.Fortran.Parser.Fixed.Fortran66: programParser :: LexAction (ProgramFile A0)
+ Language.Fortran.Parser.Fixed.Fortran66: statementParser :: LexAction (Statement A0)
+ Language.Fortran.Parser.Fixed.Fortran77: blockParser :: LexAction (Block A0)
+ Language.Fortran.Parser.Fixed.Fortran77: expressionParser :: LexAction (Expression A0)
+ Language.Fortran.Parser.Fixed.Fortran77: includesParser :: LexAction [Block A0]
+ Language.Fortran.Parser.Fixed.Fortran77: programParser :: LexAction (ProgramFile A0)
+ Language.Fortran.Parser.Fixed.Fortran77: statementParser :: LexAction (Statement A0)
+ Language.Fortran.Parser.Fixed.Lexer: AlexInput :: ByteString -> Int -> Position -> [Word8] -> Char -> Lexeme -> Int -> Int -> Maybe Token -> [Token] -> Bool -> Bool -> FortranVersion -> AlexInput
+ Language.Fortran.Parser.Fixed.Lexer: TAmpersand :: SrcSpan -> Token
+ Language.Fortran.Parser.Fixed.Lexer: TAssign :: SrcSpan -> Token
+ Language.Fortran.Parser.Fixed.Lexer: TAutomatic :: SrcSpan -> Token
+ Language.Fortran.Parser.Fixed.Lexer: TBackspace :: SrcSpan -> Token
+ Language.Fortran.Parser.Fixed.Lexer: TBlob :: SrcSpan -> String -> Token
+ Language.Fortran.Parser.Fixed.Lexer: TBlockData :: SrcSpan -> Token
+ Language.Fortran.Parser.Fixed.Lexer: TBool :: SrcSpan -> Bool -> Token
+ Language.Fortran.Parser.Fixed.Lexer: TBozLiteral :: SrcSpan -> Boz -> Token
+ Language.Fortran.Parser.Fixed.Lexer: TCall :: SrcSpan -> Token
+ Language.Fortran.Parser.Fixed.Lexer: TCase :: SrcSpan -> Token
+ Language.Fortran.Parser.Fixed.Lexer: TCaseDefault :: SrcSpan -> Token
+ Language.Fortran.Parser.Fixed.Lexer: TClose :: SrcSpan -> Token
+ Language.Fortran.Parser.Fixed.Lexer: TColon :: SrcSpan -> Token
+ Language.Fortran.Parser.Fixed.Lexer: TComma :: SrcSpan -> Token
+ Language.Fortran.Parser.Fixed.Lexer: TComment :: SrcSpan -> String -> Token
+ Language.Fortran.Parser.Fixed.Lexer: TCommon :: SrcSpan -> Token
+ Language.Fortran.Parser.Fixed.Lexer: TContinue :: SrcSpan -> Token
+ Language.Fortran.Parser.Fixed.Lexer: TCycle :: SrcSpan -> Token
+ Language.Fortran.Parser.Fixed.Lexer: TData :: SrcSpan -> Token
+ Language.Fortran.Parser.Fixed.Lexer: TDimension :: SrcSpan -> Token
+ Language.Fortran.Parser.Fixed.Lexer: TDo :: SrcSpan -> Token
+ Language.Fortran.Parser.Fixed.Lexer: TDoWhile :: SrcSpan -> Token
+ Language.Fortran.Parser.Fixed.Lexer: TDot :: SrcSpan -> Token
+ Language.Fortran.Parser.Fixed.Lexer: TEOF :: SrcSpan -> Token
+ Language.Fortran.Parser.Fixed.Lexer: TElse :: SrcSpan -> Token
+ Language.Fortran.Parser.Fixed.Lexer: TElsif :: SrcSpan -> Token
+ Language.Fortran.Parser.Fixed.Lexer: TEnd :: SrcSpan -> Token
+ Language.Fortran.Parser.Fixed.Lexer: TEndDo :: SrcSpan -> Token
+ Language.Fortran.Parser.Fixed.Lexer: TEndFunction :: SrcSpan -> Token
+ Language.Fortran.Parser.Fixed.Lexer: TEndMap :: SrcSpan -> Token
+ Language.Fortran.Parser.Fixed.Lexer: TEndProgram :: SrcSpan -> Token
+ Language.Fortran.Parser.Fixed.Lexer: TEndSelect :: SrcSpan -> Token
+ Language.Fortran.Parser.Fixed.Lexer: TEndStructure :: SrcSpan -> Token
+ Language.Fortran.Parser.Fixed.Lexer: TEndSubroutine :: SrcSpan -> Token
+ Language.Fortran.Parser.Fixed.Lexer: TEndUnion :: SrcSpan -> Token
+ Language.Fortran.Parser.Fixed.Lexer: TEndfile :: SrcSpan -> Token
+ Language.Fortran.Parser.Fixed.Lexer: TEndif :: SrcSpan -> Token
+ Language.Fortran.Parser.Fixed.Lexer: TEntry :: SrcSpan -> Token
+ Language.Fortran.Parser.Fixed.Lexer: TEquivalence :: SrcSpan -> Token
+ Language.Fortran.Parser.Fixed.Lexer: TExit :: SrcSpan -> Token
+ Language.Fortran.Parser.Fixed.Lexer: TExponent :: SrcSpan -> String -> Token
+ Language.Fortran.Parser.Fixed.Lexer: TExternal :: SrcSpan -> Token
+ Language.Fortran.Parser.Fixed.Lexer: TFormat :: SrcSpan -> Token
+ Language.Fortran.Parser.Fixed.Lexer: TFunction :: SrcSpan -> Token
+ Language.Fortran.Parser.Fixed.Lexer: TGoto :: SrcSpan -> Token
+ Language.Fortran.Parser.Fixed.Lexer: THollerith :: SrcSpan -> String -> Token
+ Language.Fortran.Parser.Fixed.Lexer: TId :: SrcSpan -> String -> Token
+ Language.Fortran.Parser.Fixed.Lexer: TIf :: SrcSpan -> Token
+ Language.Fortran.Parser.Fixed.Lexer: TImplicit :: SrcSpan -> Token
+ Language.Fortran.Parser.Fixed.Lexer: TInclude :: SrcSpan -> Token
+ Language.Fortran.Parser.Fixed.Lexer: TInquire :: SrcSpan -> Token
+ Language.Fortran.Parser.Fixed.Lexer: TInt :: SrcSpan -> String -> Token
+ Language.Fortran.Parser.Fixed.Lexer: TIntrinsic :: SrcSpan -> Token
+ Language.Fortran.Parser.Fixed.Lexer: TLabel :: SrcSpan -> String -> Token
+ Language.Fortran.Parser.Fixed.Lexer: TLeftArrayPar :: SrcSpan -> Token
+ Language.Fortran.Parser.Fixed.Lexer: TLeftPar :: SrcSpan -> Token
+ Language.Fortran.Parser.Fixed.Lexer: TMap :: SrcSpan -> Token
+ Language.Fortran.Parser.Fixed.Lexer: TNewline :: SrcSpan -> Token
+ Language.Fortran.Parser.Fixed.Lexer: TNone :: SrcSpan -> Token
+ Language.Fortran.Parser.Fixed.Lexer: TOpAnd :: SrcSpan -> Token
+ Language.Fortran.Parser.Fixed.Lexer: TOpAssign :: SrcSpan -> Token
+ Language.Fortran.Parser.Fixed.Lexer: TOpEQ :: SrcSpan -> Token
+ Language.Fortran.Parser.Fixed.Lexer: TOpEquivalent :: SrcSpan -> Token
+ Language.Fortran.Parser.Fixed.Lexer: TOpExp :: SrcSpan -> Token
+ Language.Fortran.Parser.Fixed.Lexer: TOpGE :: SrcSpan -> Token
+ Language.Fortran.Parser.Fixed.Lexer: TOpGT :: SrcSpan -> Token
+ Language.Fortran.Parser.Fixed.Lexer: TOpLE :: SrcSpan -> Token
+ Language.Fortran.Parser.Fixed.Lexer: TOpLT :: SrcSpan -> Token
+ Language.Fortran.Parser.Fixed.Lexer: TOpMinus :: SrcSpan -> Token
+ Language.Fortran.Parser.Fixed.Lexer: TOpNE :: SrcSpan -> Token
+ Language.Fortran.Parser.Fixed.Lexer: TOpNot :: SrcSpan -> Token
+ Language.Fortran.Parser.Fixed.Lexer: TOpNotEquivalent :: SrcSpan -> Token
+ Language.Fortran.Parser.Fixed.Lexer: TOpOr :: SrcSpan -> Token
+ Language.Fortran.Parser.Fixed.Lexer: TOpPlus :: SrcSpan -> Token
+ Language.Fortran.Parser.Fixed.Lexer: TOpXOr :: SrcSpan -> Token
+ Language.Fortran.Parser.Fixed.Lexer: TOpen :: SrcSpan -> Token
+ Language.Fortran.Parser.Fixed.Lexer: TParameter :: SrcSpan -> Token
+ Language.Fortran.Parser.Fixed.Lexer: TPause :: SrcSpan -> Token
+ Language.Fortran.Parser.Fixed.Lexer: TPercent :: SrcSpan -> Token
+ Language.Fortran.Parser.Fixed.Lexer: TPointer :: SrcSpan -> Token
+ Language.Fortran.Parser.Fixed.Lexer: TPrint :: SrcSpan -> Token
+ Language.Fortran.Parser.Fixed.Lexer: TProgram :: SrcSpan -> Token
+ Language.Fortran.Parser.Fixed.Lexer: TRead :: SrcSpan -> Token
+ Language.Fortran.Parser.Fixed.Lexer: TRecord :: SrcSpan -> Token
+ Language.Fortran.Parser.Fixed.Lexer: TReturn :: SrcSpan -> Token
+ Language.Fortran.Parser.Fixed.Lexer: TRewind :: SrcSpan -> Token
+ Language.Fortran.Parser.Fixed.Lexer: TRightArrayPar :: SrcSpan -> Token
+ Language.Fortran.Parser.Fixed.Lexer: TRightPar :: SrcSpan -> Token
+ Language.Fortran.Parser.Fixed.Lexer: TSave :: SrcSpan -> Token
+ Language.Fortran.Parser.Fixed.Lexer: TSelectCase :: SrcSpan -> Token
+ Language.Fortran.Parser.Fixed.Lexer: TSlash :: SrcSpan -> Token
+ Language.Fortran.Parser.Fixed.Lexer: TStar :: SrcSpan -> Token
+ Language.Fortran.Parser.Fixed.Lexer: TStatic :: SrcSpan -> Token
+ Language.Fortran.Parser.Fixed.Lexer: TStop :: SrcSpan -> Token
+ Language.Fortran.Parser.Fixed.Lexer: TString :: SrcSpan -> String -> Token
+ Language.Fortran.Parser.Fixed.Lexer: TStructure :: SrcSpan -> Token
+ Language.Fortran.Parser.Fixed.Lexer: TSubroutine :: SrcSpan -> Token
+ Language.Fortran.Parser.Fixed.Lexer: TThen :: SrcSpan -> Token
+ Language.Fortran.Parser.Fixed.Lexer: TTo :: SrcSpan -> Token
+ Language.Fortran.Parser.Fixed.Lexer: TType :: SrcSpan -> String -> Token
+ Language.Fortran.Parser.Fixed.Lexer: TTypePrint :: SrcSpan -> Token
+ Language.Fortran.Parser.Fixed.Lexer: TUnion :: SrcSpan -> Token
+ Language.Fortran.Parser.Fixed.Lexer: TWhile :: SrcSpan -> Token
+ Language.Fortran.Parser.Fixed.Lexer: TWrite :: SrcSpan -> Token
+ Language.Fortran.Parser.Fixed.Lexer: [aiBytes] :: AlexInput -> [Word8]
+ Language.Fortran.Parser.Fixed.Lexer: [aiCaseSensitive] :: AlexInput -> Bool
+ Language.Fortran.Parser.Fixed.Lexer: [aiEndOffset] :: AlexInput -> Int
+ Language.Fortran.Parser.Fixed.Lexer: [aiFortranVersion] :: AlexInput -> FortranVersion
+ Language.Fortran.Parser.Fixed.Lexer: [aiInFormat] :: AlexInput -> Bool
+ Language.Fortran.Parser.Fixed.Lexer: [aiLexeme] :: AlexInput -> Lexeme
+ Language.Fortran.Parser.Fixed.Lexer: [aiPosition] :: AlexInput -> Position
+ Language.Fortran.Parser.Fixed.Lexer: [aiPreviousChar] :: AlexInput -> Char
+ Language.Fortran.Parser.Fixed.Lexer: [aiPreviousToken] :: AlexInput -> Maybe Token
+ Language.Fortran.Parser.Fixed.Lexer: [aiPreviousTokensInLine] :: AlexInput -> [Token]
+ Language.Fortran.Parser.Fixed.Lexer: [aiSourceBytes] :: AlexInput -> ByteString
+ Language.Fortran.Parser.Fixed.Lexer: [aiStartCode] :: AlexInput -> Int
+ Language.Fortran.Parser.Fixed.Lexer: [aiWhiteSensitiveCharCount] :: AlexInput -> Int
+ Language.Fortran.Parser.Fixed.Lexer: data AlexInput
+ Language.Fortran.Parser.Fixed.Lexer: data Token
+ Language.Fortran.Parser.Fixed.Lexer: instance Data.Data.Data Language.Fortran.Parser.Fixed.Lexer.Token
+ Language.Fortran.Parser.Fixed.Lexer: instance GHC.Classes.Eq Language.Fortran.Parser.Fixed.Lexer.Token
+ Language.Fortran.Parser.Fixed.Lexer: instance GHC.Classes.Ord Language.Fortran.Parser.Fixed.Lexer.Token
+ Language.Fortran.Parser.Fixed.Lexer: instance GHC.Generics.Generic Language.Fortran.Parser.Fixed.Lexer.Token
+ Language.Fortran.Parser.Fixed.Lexer: instance GHC.Show.Show Language.Fortran.Parser.Fixed.Lexer.AlexInput
+ Language.Fortran.Parser.Fixed.Lexer: instance GHC.Show.Show Language.Fortran.Parser.Fixed.Lexer.Lexeme
+ Language.Fortran.Parser.Fixed.Lexer: instance GHC.Show.Show Language.Fortran.Parser.Fixed.Lexer.Token
+ Language.Fortran.Parser.Fixed.Lexer: instance Language.Fortran.Parser.Monad.LastToken Language.Fortran.Parser.Fixed.Lexer.AlexInput Language.Fortran.Parser.Fixed.Lexer.Token
+ Language.Fortran.Parser.Fixed.Lexer: instance Language.Fortran.Parser.Monad.Tok Language.Fortran.Parser.Fixed.Lexer.Token
+ Language.Fortran.Parser.Fixed.Lexer: instance Language.Fortran.Util.FirstParameter.FirstParameter Language.Fortran.Parser.Fixed.Lexer.Token Language.Fortran.Util.Position.SrcSpan
+ Language.Fortran.Parser.Fixed.Lexer: instance Language.Fortran.Util.FirstParameter.FirstParameter Language.Fortran.Parser.Fixed.Lexer.Token Language.Fortran.Util.Position.SrcSpan => Language.Fortran.Util.Position.Spanned Language.Fortran.Parser.Fixed.Lexer.Token
+ Language.Fortran.Parser.Fixed.Lexer: instance Language.Fortran.Util.Position.Loc Language.Fortran.Parser.Fixed.Lexer.AlexInput
+ Language.Fortran.Parser.Fixed.Lexer: instance Language.Fortran.Util.Position.Spanned Language.Fortran.Parser.Fixed.Lexer.Lexeme
+ Language.Fortran.Parser.Fixed.Lexer: lexN :: Int -> LexAction (Maybe String)
+ Language.Fortran.Parser.Fixed.Lexer: lexemeMatch :: Lexeme -> String
+ Language.Fortran.Parser.Fixed.Lexer: lexer :: (Token -> LexAction a) -> LexAction a
+ Language.Fortran.Parser.Fixed.Lexer: lexer' :: LexAction Token
+ Language.Fortran.Parser.Fixed.Lexer: type LexAction a = Parse AlexInput Token a
+ Language.Fortran.Parser.Fixed.Lexer: vanillaAlexInput :: String -> FortranVersion -> ByteString -> AlexInput
+ Language.Fortran.Parser.Fixed.Utils: convCmts :: [Block a] -> [ProgramUnit a]
+ Language.Fortran.Parser.Fixed.Utils: makeRealLit :: Maybe Token -> Maybe Token -> Maybe Token -> Maybe (SrcSpan, String) -> Expression A0
+ Language.Fortran.Parser.Fixed.Utils: parseError :: Token -> LexAction a
+ Language.Fortran.Parser.Free.Fortran2003: blockParser :: LexAction (Block A0)
+ Language.Fortran.Parser.Free.Fortran2003: expressionParser :: LexAction (Expression A0)
+ Language.Fortran.Parser.Free.Fortran2003: functionParser :: LexAction (ProgramUnit A0)
+ Language.Fortran.Parser.Free.Fortran2003: programParser :: LexAction (ProgramFile A0)
+ Language.Fortran.Parser.Free.Fortran2003: statementParser :: LexAction (Statement A0)
+ Language.Fortran.Parser.Free.Fortran90: blockParser :: LexAction (Block A0)
+ Language.Fortran.Parser.Free.Fortran90: expressionParser :: LexAction (Expression A0)
+ Language.Fortran.Parser.Free.Fortran90: functionParser :: LexAction (ProgramUnit A0)
+ Language.Fortran.Parser.Free.Fortran90: programParser :: LexAction (ProgramFile A0)
+ Language.Fortran.Parser.Free.Fortran90: statementParser :: LexAction (Statement A0)
+ Language.Fortran.Parser.Free.Fortran95: blockParser :: LexAction (Block A0)
+ Language.Fortran.Parser.Free.Fortran95: expressionParser :: LexAction (Expression A0)
+ Language.Fortran.Parser.Free.Fortran95: functionParser :: LexAction (ProgramUnit A0)
+ Language.Fortran.Parser.Free.Fortran95: programParser :: LexAction (ProgramFile A0)
+ Language.Fortran.Parser.Free.Fortran95: statementParser :: LexAction (Statement A0)
+ Language.Fortran.Parser.Free.Lexer: AlexInput :: !ByteString -> {-# UNPACK #-} !Position -> {-# UNPACK #-} !Int -> {-# UNPACK #-} !Char -> {-# UNPACK #-} !Lexeme -> {-# UNPACK #-} !StartCode -> !Maybe Token -> ![Token] -> AlexInput
+ Language.Fortran.Parser.Free.Lexer: Return :: StartCodeStatus
+ Language.Fortran.Parser.Free.Lexer: Stable :: StartCodeStatus
+ Language.Fortran.Parser.Free.Lexer: StartCode :: {-# UNPACK #-} !Int -> !StartCodeStatus -> StartCode
+ Language.Fortran.Parser.Free.Lexer: TAbstract :: SrcSpan -> Token
+ Language.Fortran.Parser.Free.Lexer: TAllocatable :: SrcSpan -> Token
+ Language.Fortran.Parser.Free.Lexer: TAllocate :: SrcSpan -> Token
+ Language.Fortran.Parser.Free.Lexer: TArrow :: SrcSpan -> Token
+ Language.Fortran.Parser.Free.Lexer: TAssign :: SrcSpan -> Token
+ Language.Fortran.Parser.Free.Lexer: TAssignment :: SrcSpan -> Token
+ Language.Fortran.Parser.Free.Lexer: TAssociate :: SrcSpan -> Token
+ Language.Fortran.Parser.Free.Lexer: TAsynchronous :: SrcSpan -> Token
+ Language.Fortran.Parser.Free.Lexer: TBackspace :: SrcSpan -> Token
+ Language.Fortran.Parser.Free.Lexer: TBind :: SrcSpan -> Token
+ Language.Fortran.Parser.Free.Lexer: TBlob :: SrcSpan -> String -> Token
+ Language.Fortran.Parser.Free.Lexer: TBlockData :: SrcSpan -> Token
+ Language.Fortran.Parser.Free.Lexer: TBozLiteral :: SrcSpan -> Boz -> Token
+ Language.Fortran.Parser.Free.Lexer: TC :: SrcSpan -> Token
+ Language.Fortran.Parser.Free.Lexer: TCall :: SrcSpan -> Token
+ Language.Fortran.Parser.Free.Lexer: TCase :: SrcSpan -> Token
+ Language.Fortran.Parser.Free.Lexer: TCharacter :: SrcSpan -> Token
+ Language.Fortran.Parser.Free.Lexer: TClass :: SrcSpan -> Token
+ Language.Fortran.Parser.Free.Lexer: TClose :: SrcSpan -> Token
+ Language.Fortran.Parser.Free.Lexer: TColon :: SrcSpan -> Token
+ Language.Fortran.Parser.Free.Lexer: TComma :: SrcSpan -> Token
+ Language.Fortran.Parser.Free.Lexer: TComma2 :: SrcSpan -> Token
+ Language.Fortran.Parser.Free.Lexer: TComment :: SrcSpan -> String -> Token
+ Language.Fortran.Parser.Free.Lexer: TCommon :: SrcSpan -> Token
+ Language.Fortran.Parser.Free.Lexer: TComplex :: SrcSpan -> Token
+ Language.Fortran.Parser.Free.Lexer: TContains :: SrcSpan -> Token
+ Language.Fortran.Parser.Free.Lexer: TContinue :: SrcSpan -> Token
+ Language.Fortran.Parser.Free.Lexer: TCycle :: SrcSpan -> Token
+ Language.Fortran.Parser.Free.Lexer: TData :: SrcSpan -> Token
+ Language.Fortran.Parser.Free.Lexer: TDeallocate :: SrcSpan -> Token
+ Language.Fortran.Parser.Free.Lexer: TDefault :: SrcSpan -> Token
+ Language.Fortran.Parser.Free.Lexer: TDimension :: SrcSpan -> Token
+ Language.Fortran.Parser.Free.Lexer: TDo :: SrcSpan -> Token
+ Language.Fortran.Parser.Free.Lexer: TDoubleColon :: SrcSpan -> Token
+ Language.Fortran.Parser.Free.Lexer: TDoublePrecision :: SrcSpan -> Token
+ Language.Fortran.Parser.Free.Lexer: TEOF :: SrcSpan -> Token
+ Language.Fortran.Parser.Free.Lexer: TElemental :: SrcSpan -> Token
+ Language.Fortran.Parser.Free.Lexer: TElse :: SrcSpan -> Token
+ Language.Fortran.Parser.Free.Lexer: TElsewhere :: SrcSpan -> Token
+ Language.Fortran.Parser.Free.Lexer: TElsif :: SrcSpan -> Token
+ Language.Fortran.Parser.Free.Lexer: TEnd :: SrcSpan -> Token
+ Language.Fortran.Parser.Free.Lexer: TEndAssociate :: SrcSpan -> Token
+ Language.Fortran.Parser.Free.Lexer: TEndBlockData :: SrcSpan -> Token
+ Language.Fortran.Parser.Free.Lexer: TEndDo :: SrcSpan -> Token
+ Language.Fortran.Parser.Free.Lexer: TEndEnum :: SrcSpan -> Token
+ Language.Fortran.Parser.Free.Lexer: TEndForall :: SrcSpan -> Token
+ Language.Fortran.Parser.Free.Lexer: TEndFunction :: SrcSpan -> Token
+ Language.Fortran.Parser.Free.Lexer: TEndIf :: SrcSpan -> Token
+ Language.Fortran.Parser.Free.Lexer: TEndInterface :: SrcSpan -> Token
+ Language.Fortran.Parser.Free.Lexer: TEndModule :: SrcSpan -> Token
+ Language.Fortran.Parser.Free.Lexer: TEndProgram :: SrcSpan -> Token
+ Language.Fortran.Parser.Free.Lexer: TEndSelect :: SrcSpan -> Token
+ Language.Fortran.Parser.Free.Lexer: TEndSubroutine :: SrcSpan -> Token
+ Language.Fortran.Parser.Free.Lexer: TEndType :: SrcSpan -> Token
+ Language.Fortran.Parser.Free.Lexer: TEndWhere :: SrcSpan -> Token
+ Language.Fortran.Parser.Free.Lexer: TEndfile :: SrcSpan -> Token
+ Language.Fortran.Parser.Free.Lexer: TEntry :: SrcSpan -> Token
+ Language.Fortran.Parser.Free.Lexer: TEnum :: SrcSpan -> Token
+ Language.Fortran.Parser.Free.Lexer: TEnumerator :: SrcSpan -> Token
+ Language.Fortran.Parser.Free.Lexer: TEquivalence :: SrcSpan -> Token
+ Language.Fortran.Parser.Free.Lexer: TErr :: SrcSpan -> Token
+ Language.Fortran.Parser.Free.Lexer: TErrMsg :: SrcSpan -> Token
+ Language.Fortran.Parser.Free.Lexer: TExit :: SrcSpan -> Token
+ Language.Fortran.Parser.Free.Lexer: TExternal :: SrcSpan -> Token
+ Language.Fortran.Parser.Free.Lexer: TFlush :: SrcSpan -> Token
+ Language.Fortran.Parser.Free.Lexer: TForall :: SrcSpan -> Token
+ Language.Fortran.Parser.Free.Lexer: TFormat :: SrcSpan -> Token
+ Language.Fortran.Parser.Free.Lexer: TFunction :: SrcSpan -> Token
+ Language.Fortran.Parser.Free.Lexer: TGoto :: SrcSpan -> Token
+ Language.Fortran.Parser.Free.Lexer: TIOMsg :: SrcSpan -> Token
+ Language.Fortran.Parser.Free.Lexer: TIOStat :: SrcSpan -> Token
+ Language.Fortran.Parser.Free.Lexer: TId :: SrcSpan -> String -> Token
+ Language.Fortran.Parser.Free.Lexer: TIf :: SrcSpan -> Token
+ Language.Fortran.Parser.Free.Lexer: TImplicit :: SrcSpan -> Token
+ Language.Fortran.Parser.Free.Lexer: TImport :: SrcSpan -> Token
+ Language.Fortran.Parser.Free.Lexer: TIn :: SrcSpan -> Token
+ Language.Fortran.Parser.Free.Lexer: TInOut :: SrcSpan -> Token
+ Language.Fortran.Parser.Free.Lexer: TInclude :: SrcSpan -> Token
+ Language.Fortran.Parser.Free.Lexer: TInquire :: SrcSpan -> Token
+ Language.Fortran.Parser.Free.Lexer: TInteger :: SrcSpan -> Token
+ Language.Fortran.Parser.Free.Lexer: TIntegerLiteral :: SrcSpan -> String -> Token
+ Language.Fortran.Parser.Free.Lexer: TIntent :: SrcSpan -> Token
+ Language.Fortran.Parser.Free.Lexer: TInterface :: SrcSpan -> Token
+ Language.Fortran.Parser.Free.Lexer: TIntrinsic :: SrcSpan -> Token
+ Language.Fortran.Parser.Free.Lexer: TKind :: SrcSpan -> Token
+ Language.Fortran.Parser.Free.Lexer: TLeftInitPar :: SrcSpan -> Token
+ Language.Fortran.Parser.Free.Lexer: TLeftPar :: SrcSpan -> Token
+ Language.Fortran.Parser.Free.Lexer: TLeftPar2 :: SrcSpan -> Token
+ Language.Fortran.Parser.Free.Lexer: TLen :: SrcSpan -> Token
+ Language.Fortran.Parser.Free.Lexer: TLogical :: SrcSpan -> Token
+ Language.Fortran.Parser.Free.Lexer: TLogicalLiteral :: SrcSpan -> Bool -> Token
+ Language.Fortran.Parser.Free.Lexer: TModule :: SrcSpan -> Token
+ Language.Fortran.Parser.Free.Lexer: TModuleProcedure :: SrcSpan -> Token
+ Language.Fortran.Parser.Free.Lexer: TName :: SrcSpan -> Token
+ Language.Fortran.Parser.Free.Lexer: TNamelist :: SrcSpan -> Token
+ Language.Fortran.Parser.Free.Lexer: TNewline :: SrcSpan -> Token
+ Language.Fortran.Parser.Free.Lexer: TNonIntrinsic :: SrcSpan -> Token
+ Language.Fortran.Parser.Free.Lexer: TNone :: SrcSpan -> Token
+ Language.Fortran.Parser.Free.Lexer: TNullify :: SrcSpan -> Token
+ Language.Fortran.Parser.Free.Lexer: TOnly :: SrcSpan -> Token
+ Language.Fortran.Parser.Free.Lexer: TOpAnd :: SrcSpan -> Token
+ Language.Fortran.Parser.Free.Lexer: TOpAssign :: SrcSpan -> Token
+ Language.Fortran.Parser.Free.Lexer: TOpCustom :: SrcSpan -> String -> Token
+ Language.Fortran.Parser.Free.Lexer: TOpDivision :: SrcSpan -> Token
+ Language.Fortran.Parser.Free.Lexer: TOpEQ :: SrcSpan -> Token
+ Language.Fortran.Parser.Free.Lexer: TOpEquivalent :: SrcSpan -> Token
+ Language.Fortran.Parser.Free.Lexer: TOpExp :: SrcSpan -> Token
+ Language.Fortran.Parser.Free.Lexer: TOpGE :: SrcSpan -> Token
+ Language.Fortran.Parser.Free.Lexer: TOpGT :: SrcSpan -> Token
+ Language.Fortran.Parser.Free.Lexer: TOpLE :: SrcSpan -> Token
+ Language.Fortran.Parser.Free.Lexer: TOpLT :: SrcSpan -> Token
+ Language.Fortran.Parser.Free.Lexer: TOpMinus :: SrcSpan -> Token
+ Language.Fortran.Parser.Free.Lexer: TOpNE :: SrcSpan -> Token
+ Language.Fortran.Parser.Free.Lexer: TOpNot :: SrcSpan -> Token
+ Language.Fortran.Parser.Free.Lexer: TOpNotEquivalent :: SrcSpan -> Token
+ Language.Fortran.Parser.Free.Lexer: TOpOr :: SrcSpan -> Token
+ Language.Fortran.Parser.Free.Lexer: TOpPlus :: SrcSpan -> Token
+ Language.Fortran.Parser.Free.Lexer: TOpen :: SrcSpan -> Token
+ Language.Fortran.Parser.Free.Lexer: TOperator :: SrcSpan -> Token
+ Language.Fortran.Parser.Free.Lexer: TOptional :: SrcSpan -> Token
+ Language.Fortran.Parser.Free.Lexer: TOut :: SrcSpan -> Token
+ Language.Fortran.Parser.Free.Lexer: TParameter :: SrcSpan -> Token
+ Language.Fortran.Parser.Free.Lexer: TPause :: SrcSpan -> Token
+ Language.Fortran.Parser.Free.Lexer: TPercent :: SrcSpan -> Token
+ Language.Fortran.Parser.Free.Lexer: TPointer :: SrcSpan -> Token
+ Language.Fortran.Parser.Free.Lexer: TPrint :: SrcSpan -> Token
+ Language.Fortran.Parser.Free.Lexer: TPrivate :: SrcSpan -> Token
+ Language.Fortran.Parser.Free.Lexer: TProcedure :: SrcSpan -> Token
+ Language.Fortran.Parser.Free.Lexer: TProgram :: SrcSpan -> Token
+ Language.Fortran.Parser.Free.Lexer: TProtected :: SrcSpan -> Token
+ Language.Fortran.Parser.Free.Lexer: TPublic :: SrcSpan -> Token
+ Language.Fortran.Parser.Free.Lexer: TPure :: SrcSpan -> Token
+ Language.Fortran.Parser.Free.Lexer: TRead :: SrcSpan -> Token
+ Language.Fortran.Parser.Free.Lexer: TReal :: SrcSpan -> Token
+ Language.Fortran.Parser.Free.Lexer: TRealLiteral :: SrcSpan -> RealLit -> Token
+ Language.Fortran.Parser.Free.Lexer: TRecursive :: SrcSpan -> Token
+ Language.Fortran.Parser.Free.Lexer: TResult :: SrcSpan -> Token
+ Language.Fortran.Parser.Free.Lexer: TReturn :: SrcSpan -> Token
+ Language.Fortran.Parser.Free.Lexer: TRewind :: SrcSpan -> Token
+ Language.Fortran.Parser.Free.Lexer: TRightInitPar :: SrcSpan -> Token
+ Language.Fortran.Parser.Free.Lexer: TRightPar :: SrcSpan -> Token
+ Language.Fortran.Parser.Free.Lexer: TSave :: SrcSpan -> Token
+ Language.Fortran.Parser.Free.Lexer: TSelectCase :: SrcSpan -> Token
+ Language.Fortran.Parser.Free.Lexer: TSemiColon :: SrcSpan -> Token
+ Language.Fortran.Parser.Free.Lexer: TSequence :: SrcSpan -> Token
+ Language.Fortran.Parser.Free.Lexer: TSlash :: SrcSpan -> Token
+ Language.Fortran.Parser.Free.Lexer: TSource :: SrcSpan -> Token
+ Language.Fortran.Parser.Free.Lexer: TStar :: SrcSpan -> Token
+ Language.Fortran.Parser.Free.Lexer: TStat :: SrcSpan -> Token
+ Language.Fortran.Parser.Free.Lexer: TStop :: SrcSpan -> Token
+ Language.Fortran.Parser.Free.Lexer: TString :: SrcSpan -> String -> Token
+ Language.Fortran.Parser.Free.Lexer: TSubroutine :: SrcSpan -> Token
+ Language.Fortran.Parser.Free.Lexer: TTarget :: SrcSpan -> Token
+ Language.Fortran.Parser.Free.Lexer: TThen :: SrcSpan -> Token
+ Language.Fortran.Parser.Free.Lexer: TTo :: SrcSpan -> Token
+ Language.Fortran.Parser.Free.Lexer: TType :: SrcSpan -> Token
+ Language.Fortran.Parser.Free.Lexer: TUnderscore :: SrcSpan -> Token
+ Language.Fortran.Parser.Free.Lexer: TUnit :: SrcSpan -> Token
+ Language.Fortran.Parser.Free.Lexer: TUse :: SrcSpan -> Token
+ Language.Fortran.Parser.Free.Lexer: TValue :: SrcSpan -> Token
+ Language.Fortran.Parser.Free.Lexer: TVolatile :: SrcSpan -> Token
+ Language.Fortran.Parser.Free.Lexer: TWhere :: SrcSpan -> Token
+ Language.Fortran.Parser.Free.Lexer: TWhile :: SrcSpan -> Token
+ Language.Fortran.Parser.Free.Lexer: TWrite :: SrcSpan -> Token
+ Language.Fortran.Parser.Free.Lexer: [aiEndOffset] :: AlexInput -> {-# UNPACK #-} !Int
+ Language.Fortran.Parser.Free.Lexer: [aiLexeme] :: AlexInput -> {-# UNPACK #-} !Lexeme
+ Language.Fortran.Parser.Free.Lexer: [aiPosition] :: AlexInput -> {-# UNPACK #-} !Position
+ Language.Fortran.Parser.Free.Lexer: [aiPreviousChar] :: AlexInput -> {-# UNPACK #-} !Char
+ Language.Fortran.Parser.Free.Lexer: [aiPreviousToken] :: AlexInput -> !Maybe Token
+ Language.Fortran.Parser.Free.Lexer: [aiPreviousTokensInLine] :: AlexInput -> ![Token]
+ Language.Fortran.Parser.Free.Lexer: [aiSourceBytes] :: AlexInput -> !ByteString
+ Language.Fortran.Parser.Free.Lexer: [aiStartCode] :: AlexInput -> {-# UNPACK #-} !StartCode
+ Language.Fortran.Parser.Free.Lexer: [scActual] :: StartCode -> {-# UNPACK #-} !Int
+ Language.Fortran.Parser.Free.Lexer: [scStatus] :: StartCode -> !StartCodeStatus
+ Language.Fortran.Parser.Free.Lexer: data AlexInput
+ Language.Fortran.Parser.Free.Lexer: data StartCode
+ Language.Fortran.Parser.Free.Lexer: data StartCodeStatus
+ Language.Fortran.Parser.Free.Lexer: data Token
+ Language.Fortran.Parser.Free.Lexer: instance Data.Data.Data Language.Fortran.Parser.Free.Lexer.Token
+ Language.Fortran.Parser.Free.Lexer: instance GHC.Classes.Eq Language.Fortran.Parser.Free.Lexer.Token
+ Language.Fortran.Parser.Free.Lexer: instance GHC.Generics.Generic Language.Fortran.Parser.Free.Lexer.Token
+ Language.Fortran.Parser.Free.Lexer: instance GHC.Show.Show Language.Fortran.Parser.Free.Lexer.AlexInput
+ Language.Fortran.Parser.Free.Lexer: instance GHC.Show.Show Language.Fortran.Parser.Free.Lexer.Lexeme
+ Language.Fortran.Parser.Free.Lexer: instance GHC.Show.Show Language.Fortran.Parser.Free.Lexer.StartCode
+ Language.Fortran.Parser.Free.Lexer: instance GHC.Show.Show Language.Fortran.Parser.Free.Lexer.StartCodeStatus
+ Language.Fortran.Parser.Free.Lexer: instance GHC.Show.Show Language.Fortran.Parser.Free.Lexer.Token
+ Language.Fortran.Parser.Free.Lexer: instance Language.Fortran.Parser.Free.Lexer.SpecifiesType Language.Fortran.Parser.Free.Lexer.Token
+ Language.Fortran.Parser.Free.Lexer: instance Language.Fortran.Parser.Free.Lexer.SpecifiesType [Language.Fortran.Parser.Free.Lexer.Token]
+ Language.Fortran.Parser.Free.Lexer: instance Language.Fortran.Parser.Monad.LastToken Language.Fortran.Parser.Free.Lexer.AlexInput Language.Fortran.Parser.Free.Lexer.Token
+ Language.Fortran.Parser.Free.Lexer: instance Language.Fortran.Parser.Monad.Tok Language.Fortran.Parser.Free.Lexer.Token
+ Language.Fortran.Parser.Free.Lexer: instance Language.Fortran.Util.FirstParameter.FirstParameter Language.Fortran.Parser.Free.Lexer.Token Language.Fortran.Util.Position.SrcSpan
+ Language.Fortran.Parser.Free.Lexer: instance Language.Fortran.Util.FirstParameter.FirstParameter Language.Fortran.Parser.Free.Lexer.Token Language.Fortran.Util.Position.SrcSpan => Language.Fortran.Util.Position.Spanned Language.Fortran.Parser.Free.Lexer.Token
+ Language.Fortran.Parser.Free.Lexer: instance Language.Fortran.Util.Position.Loc Language.Fortran.Parser.Free.Lexer.AlexInput
+ Language.Fortran.Parser.Free.Lexer: instance Language.Fortran.Util.Position.Spanned Language.Fortran.Parser.Free.Lexer.Lexeme
+ Language.Fortran.Parser.Free.Lexer: lexer :: (Token -> LexAction a) -> LexAction a
+ Language.Fortran.Parser.Free.Lexer: lexer' :: LexAction Token
+ Language.Fortran.Parser.Free.Lexer: scN :: Int
+ Language.Fortran.Parser.Free.Lexer: type LexAction a = Parse AlexInput Token a
+ Language.Fortran.Parser.Free.Lexer: vanillaAlexInput :: String -> ByteString -> AlexInput
+ Language.Fortran.Parser.Free.Utils: parseError :: Token -> LexAction a
+ Language.Fortran.Parser.Free.Utils: unitNameCheck :: Token -> String -> Parse AlexInput Token ()
+ Language.Fortran.Parser.LexerUtils: readIntOrBoz :: String -> Integer
+ Language.Fortran.Parser.Monad: ConCommon :: Context
+ Language.Fortran.Parser.Monad: ConData :: Context
+ Language.Fortran.Parser.Monad: ConImplicit :: Context
+ Language.Fortran.Parser.Monad: ConNamelist :: Context
+ Language.Fortran.Parser.Monad: ConStart :: Context
+ Language.Fortran.Parser.Monad: ParanthesesCount :: Integer -> Bool -> ParanthesesCount
+ Language.Fortran.Parser.Monad: Parse :: (ParseState b -> ParseResult b c a) -> Parse b c a
+ Language.Fortran.Parser.Monad: ParseError :: Position -> Maybe b -> String -> String -> ParseError a b
+ Language.Fortran.Parser.Monad: ParseErrorSimple :: Position -> String -> String -> ParseErrorSimple
+ Language.Fortran.Parser.Monad: ParseFailed :: ParseError b c -> ParseResult b c a
+ Language.Fortran.Parser.Monad: ParseOk :: a -> ParseState b -> ParseResult b c a
+ Language.Fortran.Parser.Monad: ParseState :: a -> ParanthesesCount -> FortranVersion -> String -> [Context] -> ParseState a
+ Language.Fortran.Parser.Monad: [errFilename] :: ParseError a b -> String
+ Language.Fortran.Parser.Monad: [errLastToken] :: ParseError a b -> Maybe b
+ Language.Fortran.Parser.Monad: [errMsg] :: ParseError a b -> String
+ Language.Fortran.Parser.Monad: [errPos] :: ParseError a b -> Position
+ Language.Fortran.Parser.Monad: [errorFilename] :: ParseErrorSimple -> String
+ Language.Fortran.Parser.Monad: [errorMsg] :: ParseErrorSimple -> String
+ Language.Fortran.Parser.Monad: [errorPos] :: ParseErrorSimple -> Position
+ Language.Fortran.Parser.Monad: [pcActual] :: ParanthesesCount -> Integer
+ Language.Fortran.Parser.Monad: [pcHasReached0] :: ParanthesesCount -> Bool
+ Language.Fortran.Parser.Monad: [psAlexInput] :: ParseState a -> a
+ Language.Fortran.Parser.Monad: [psContext] :: ParseState a -> [Context]
+ Language.Fortran.Parser.Monad: [psFilename] :: ParseState a -> String
+ Language.Fortran.Parser.Monad: [psParanthesesCount] :: ParseState a -> ParanthesesCount
+ Language.Fortran.Parser.Monad: [psVersion] :: ParseState a -> FortranVersion
+ Language.Fortran.Parser.Monad: [unParse] :: Parse b c a -> ParseState b -> ParseResult b c a
+ Language.Fortran.Parser.Monad: class LastToken a b | a -> b
+ Language.Fortran.Parser.Monad: class Tok a
+ Language.Fortran.Parser.Monad: data Context
+ Language.Fortran.Parser.Monad: data ParanthesesCount
+ Language.Fortran.Parser.Monad: data ParseError a b
+ Language.Fortran.Parser.Monad: data ParseErrorSimple
+ Language.Fortran.Parser.Monad: data ParseResult b c a
+ Language.Fortran.Parser.Monad: data ParseState a
+ Language.Fortran.Parser.Monad: decPar :: (Loc a, LastToken a b, Show b) => Parse a b ()
+ Language.Fortran.Parser.Monad: eofToken :: Tok a => a -> Bool
+ Language.Fortran.Parser.Monad: evalParse :: (Loc b, LastToken b c, Show c) => Parse b c a -> ParseState b -> a
+ Language.Fortran.Parser.Monad: execParse :: (Loc b, LastToken b c, Show c) => Parse b c a -> ParseState b -> ParseState b
+ Language.Fortran.Parser.Monad: getAlex :: (Loc a, LastToken a b, Show b) => Parse a b a
+ Language.Fortran.Parser.Monad: getLastToken :: (LastToken a b, Show b) => a -> Maybe b
+ Language.Fortran.Parser.Monad: getParanthesesCount :: (Loc a, LastToken a b, Show b) => Parse a b ParanthesesCount
+ Language.Fortran.Parser.Monad: getPosition :: (Loc a, LastToken a b, Show b) => Parse a b Position
+ Language.Fortran.Parser.Monad: getSrcSpan :: (Loc a, LastToken a b, Show b) => Position -> Parse a b SrcSpan
+ Language.Fortran.Parser.Monad: getVersion :: (Loc a, LastToken a b, Show b) => Parse a b FortranVersion
+ Language.Fortran.Parser.Monad: incPar :: (Loc a, LastToken a b, Show b) => Parse a b ()
+ Language.Fortran.Parser.Monad: instance (Data.Typeable.Internal.Typeable a, Data.Typeable.Internal.Typeable b, GHC.Show.Show a, GHC.Show.Show b) => GHC.Exception.Type.Exception (Language.Fortran.Parser.Monad.ParseError a b)
+ Language.Fortran.Parser.Monad: instance (Language.Fortran.Util.Position.Loc b, Language.Fortran.Parser.Monad.LastToken b c, GHC.Show.Show c) => Control.Monad.Error.Class.MonadError (Language.Fortran.Parser.Monad.ParseError b c) (Language.Fortran.Parser.Monad.Parse b c)
+ Language.Fortran.Parser.Monad: instance (Language.Fortran.Util.Position.Loc b, Language.Fortran.Parser.Monad.LastToken b c, GHC.Show.Show c) => Control.Monad.Fail.MonadFail (Language.Fortran.Parser.Monad.Parse b c)
+ Language.Fortran.Parser.Monad: instance (Language.Fortran.Util.Position.Loc b, Language.Fortran.Parser.Monad.LastToken b c, GHC.Show.Show c) => Control.Monad.State.Class.MonadState (Language.Fortran.Parser.Monad.ParseState b) (Language.Fortran.Parser.Monad.Parse b c)
+ Language.Fortran.Parser.Monad: instance (Language.Fortran.Util.Position.Loc b, Language.Fortran.Parser.Monad.LastToken b c, GHC.Show.Show c) => GHC.Base.Applicative (Language.Fortran.Parser.Monad.Parse b c)
+ Language.Fortran.Parser.Monad: instance (Language.Fortran.Util.Position.Loc b, Language.Fortran.Parser.Monad.LastToken b c, GHC.Show.Show c) => GHC.Base.Functor (Language.Fortran.Parser.Monad.Parse b c)
+ Language.Fortran.Parser.Monad: instance (Language.Fortran.Util.Position.Loc b, Language.Fortran.Parser.Monad.LastToken b c, GHC.Show.Show c) => GHC.Base.Monad (Language.Fortran.Parser.Monad.Parse b c)
+ Language.Fortran.Parser.Monad: instance GHC.Base.Functor (Language.Fortran.Parser.Monad.ParseResult b c)
+ Language.Fortran.Parser.Monad: instance GHC.Classes.Eq Language.Fortran.Parser.Monad.Context
+ Language.Fortran.Parser.Monad: instance GHC.Classes.Eq Language.Fortran.Parser.Monad.ParanthesesCount
+ Language.Fortran.Parser.Monad: instance GHC.Exception.Type.Exception Language.Fortran.Parser.Monad.ParseErrorSimple
+ Language.Fortran.Parser.Monad: instance GHC.Show.Show Language.Fortran.Parser.Monad.Context
+ Language.Fortran.Parser.Monad: instance GHC.Show.Show Language.Fortran.Parser.Monad.ParanthesesCount
+ Language.Fortran.Parser.Monad: instance GHC.Show.Show Language.Fortran.Parser.Monad.ParseErrorSimple
+ Language.Fortran.Parser.Monad: instance GHC.Show.Show a => GHC.Show.Show (Language.Fortran.Parser.Monad.ParseState a)
+ Language.Fortran.Parser.Monad: instance forall k b (a :: k). GHC.Show.Show b => GHC.Show.Show (Language.Fortran.Parser.Monad.ParseError a b)
+ Language.Fortran.Parser.Monad: newtype Parse b c a
+ Language.Fortran.Parser.Monad: popContext :: (Loc a, LastToken a b, Show b) => Parse a b ()
+ Language.Fortran.Parser.Monad: pushContext :: (Loc a, LastToken a b, Show b) => Context -> Parse a b ()
+ Language.Fortran.Parser.Monad: putAlex :: (Loc a, LastToken a b, Show b) => a -> Parse a b ()
+ Language.Fortran.Parser.Monad: resetPar :: (Loc a, LastToken a b, Show b) => Parse a b ()
+ Language.Fortran.Parser.Monad: runParse :: (Loc b, LastToken b c, Show c) => Parse b c a -> ParseState b -> ParseResult b c a
+ Language.Fortran.Parser.Monad: runParseUnsafe :: (Loc b, LastToken b c, Show c) => Parse b c a -> ParseState b -> (a, ParseState b)
+ Language.Fortran.Parser.Monad: throwIOError :: String -> a
+ Language.Fortran.Parser.Monad: tokenMsg :: Show a => Maybe a -> String
+ Language.Fortran.Parser.Monad: topContext :: (Loc a, LastToken a b, Show b) => Parse a b Context
+ Language.Fortran.PrettyPrint: instance Language.Fortran.PrettyPrint.Pretty (Language.Fortran.AST.ArgumentExpression a)
+ Language.Fortran.Transformation.Monad: getProgramFile :: Transform a (ProgramFile (Analysis a))
+ Language.Fortran.Transformation.Monad: modifyProgramFile :: (ProgramFile (Analysis a) -> ProgramFile (Analysis a)) -> Transform a ()
+ Language.Fortran.Transformation.Monad: putProgramFile :: ProgramFile (Analysis a) -> Transform a ()
+ Language.Fortran.Transformation.Monad: runTransform :: Data a => TypeEnv -> ModuleMap -> Transform a () -> ProgramFile a -> ProgramFile a
+ Language.Fortran.Transformation.Monad: type Transform a = State (TransformationState a)
+ Language.Fortran.Util.FirstParameter: instance forall k (a :: k -> *) e (b :: k -> *). (Language.Fortran.Util.FirstParameter.GFirstParameter a e, Language.Fortran.Util.FirstParameter.GFirstParameter b e) => Language.Fortran.Util.FirstParameter.GFirstParameter (a GHC.Generics.:*: b) e
+ Language.Fortran.Util.FirstParameter: instance forall k (a :: k -> *) e (b :: k -> *). (Language.Fortran.Util.FirstParameter.GFirstParameter a e, Language.Fortran.Util.FirstParameter.GFirstParameter b e) => Language.Fortran.Util.FirstParameter.GFirstParameter (a GHC.Generics.:+: b) e
+ Language.Fortran.Util.FirstParameter: instance forall k (a :: k -> *) e i (c :: GHC.Generics.Meta). Language.Fortran.Util.FirstParameter.GFirstParameter a e => Language.Fortran.Util.FirstParameter.GFirstParameter (GHC.Generics.M1 i c a) e
+ Language.Fortran.Util.ModFile: alterModFileDataF :: Functor f => (Maybe ByteString -> f (Maybe ByteString)) -> String -> ModFile -> f ModFile
+ Language.Fortran.Util.ModFile: decodeModFiles :: [FilePath] -> IO [(FilePath, ModFile)]
+ Language.Fortran.Util.ModFile: decodeModFiles' :: [FilePath] -> IO ModFiles
+ Language.Fortran.Util.ModFile: extractParamVarMap :: forall a. Data a => ProgramFile (Analysis a) -> ParamVarMap
+ Language.Fortran.Util.ModFile: extractStringMap :: Data a => a -> (a, StringMap)
+ Language.Fortran.Util.SecondParameter: instance forall k (a :: k -> *) (b :: k -> *). Language.Fortran.Util.SecondParameter.ParameterLeaf (a GHC.Generics.:*: b)
+ Language.Fortran.Util.SecondParameter: instance forall k (a :: k -> *) e (b :: k -> *). (Language.Fortran.Util.SecondParameter.GSecondParameter a e, Language.Fortran.Util.SecondParameter.GSecondParameter b e) => Language.Fortran.Util.SecondParameter.GSecondParameter (a GHC.Generics.:+: b) e
+ Language.Fortran.Util.SecondParameter: instance forall k (a :: k -> *) e (b :: k -> *). (Language.Fortran.Util.SecondParameter.ParameterLeaf a, Language.Fortran.Util.SecondParameter.GSecondParameter a e, Language.Fortran.Util.SecondParameter.GSecondParameter' b e) => Language.Fortran.Util.SecondParameter.GSecondParameter (a GHC.Generics.:*: b) e
+ Language.Fortran.Util.SecondParameter: instance forall k (a :: k -> *) e (b :: k -> *). Language.Fortran.Util.SecondParameter.GSecondParameter' a e => Language.Fortran.Util.SecondParameter.GSecondParameter' (a GHC.Generics.:*: b) e
+ Language.Fortran.Util.SecondParameter: instance forall k (a :: k -> *) e i (c :: GHC.Generics.Meta). Language.Fortran.Util.SecondParameter.GSecondParameter a e => Language.Fortran.Util.SecondParameter.GSecondParameter (GHC.Generics.M1 i c a) e
+ Language.Fortran.Util.SecondParameter: instance forall k (a :: k -> *) e i (c :: GHC.Generics.Meta). Language.Fortran.Util.SecondParameter.GSecondParameter' a e => Language.Fortran.Util.SecondParameter.GSecondParameter' (GHC.Generics.M1 i c a) e
+ Language.Fortran.Util.SecondParameter: instance forall k i (c :: GHC.Generics.Meta) (a :: k -> *). Language.Fortran.Util.SecondParameter.ParameterLeaf (GHC.Generics.M1 i c a)
- Language.Fortran.AST: Argument :: a -> SrcSpan -> Maybe String -> Expression a -> Argument a
+ Language.Fortran.AST: Argument :: a -> SrcSpan -> Maybe String -> ArgumentExpression a -> Argument a
Files
- CHANGELOG.md +11/−0
- app/Main.hs +469/−0
- fortran-src.cabal +102/−39
- src/Language/Fortran/AST.hs +22/−12
- src/Language/Fortran/AST/AList.hs +0/−6
- src/Language/Fortran/AST/Boz.hs +15/−19
- src/Language/Fortran/AST/RealLit.hs +1/−2
- src/Language/Fortran/Analysis.hs +5/−8
- src/Language/Fortran/Analysis/BBlocks.hs +7/−8
- src/Language/Fortran/Analysis/DataFlow.hs +4/−9
- src/Language/Fortran/Analysis/ModGraph.hs +13/−36
- src/Language/Fortran/Analysis/Renaming.hs +2/−2
- src/Language/Fortran/Analysis/SemanticTypes.hs +0/−3
- src/Language/Fortran/Analysis/Types.hs +2/−4
- src/Language/Fortran/Intrinsics.hs +1/−4
- src/Language/Fortran/LValue.hs +0/−6
- src/Language/Fortran/Lexer/FixedForm.x +0/−1153
- src/Language/Fortran/Lexer/FixedForm/Utils.hs +0/−19
- src/Language/Fortran/Lexer/FreeForm.x +0/−1395
- src/Language/Fortran/Parser.hs +338/−0
- src/Language/Fortran/Parser/Any.hs +0/−86
- src/Language/Fortran/Parser/Fixed/Fortran66.y +465/−0
- src/Language/Fortran/Parser/Fixed/Fortran77.y +977/−0
- src/Language/Fortran/Parser/Fixed/Lexer.x +1126/−0
- src/Language/Fortran/Parser/Fixed/Utils.hs +42/−0
- src/Language/Fortran/Parser/Fortran2003.y +0/−1477
- src/Language/Fortran/Parser/Fortran66.y +0/−512
- src/Language/Fortran/Parser/Fortran77.y +0/−1152
- src/Language/Fortran/Parser/Fortran90.y +0/−1214
- src/Language/Fortran/Parser/Fortran95.y +0/−1290
- src/Language/Fortran/Parser/Free/Fortran2003.y +1417/−0
- src/Language/Fortran/Parser/Free/Fortran90.y +1161/−0
- src/Language/Fortran/Parser/Free/Fortran95.y +1231/−0
- src/Language/Fortran/Parser/Free/Lexer.x +1377/−0
- src/Language/Fortran/Parser/Free/Utils.hs +23/−0
- src/Language/Fortran/Parser/LexerUtils.hs +18/−0
- src/Language/Fortran/Parser/Monad.hs +224/−0
- src/Language/Fortran/Parser/Utils.hs +0/−47
- src/Language/Fortran/ParserMonad.hs +0/−276
- src/Language/Fortran/PrettyPrint.hs +5/−3
- src/Language/Fortran/Transformation/Disambiguation/Function.hs +2/−3
- src/Language/Fortran/Transformation/Disambiguation/Intrinsic.hs +1/−2
- src/Language/Fortran/Transformation/Grouping.hs +5/−1
- src/Language/Fortran/Transformation/Monad.hs +42/−0
- src/Language/Fortran/Transformation/TransformMonad.hs +0/−40
- src/Language/Fortran/Transformer.hs +0/−70
- src/Language/Fortran/Util/FirstParameter.hs +0/−2
- src/Language/Fortran/Util/ModFile.hs +62/−23
- src/Language/Fortran/Util/Position.hs +0/−5
- src/Language/Fortran/Util/SecondParameter.hs +0/−2
- src/Language/Fortran/Version.hs +0/−8
- src/Main.hs +0/−482
- test/Language/Fortran/Analysis/BBlocksSpec.hs +5/−4
- test/Language/Fortran/Analysis/DataFlowSpec.hs +7/−10
- test/Language/Fortran/Analysis/RenamingSpec.hs +15/−16
- test/Language/Fortran/Analysis/TypesSpec.hs +7/−9
- test/Language/Fortran/AnalysisSpec.hs +5/−7
- test/Language/Fortran/Lexer/FixedFormSpec.hs +0/−312
- test/Language/Fortran/Lexer/FreeFormSpec.hs +0/−377
- test/Language/Fortran/Parser/Fixed/Fortran66Spec.hs +189/−0
- test/Language/Fortran/Parser/Fixed/Fortran77/IncludeSpec.hs +52/−0
- test/Language/Fortran/Parser/Fixed/Fortran77/ParserSpec.hs +412/−0
- test/Language/Fortran/Parser/Fixed/LexerSpec.hs +324/−0
- test/Language/Fortran/Parser/Fortran2003Spec.hs +0/−180
- test/Language/Fortran/Parser/Fortran2008Spec.hs +0/−8
- test/Language/Fortran/Parser/Fortran66Spec.hs +0/−190
- test/Language/Fortran/Parser/Fortran77/IncludeSpec.hs +0/−55
- test/Language/Fortran/Parser/Fortran77/ParserSpec.hs +0/−424
- test/Language/Fortran/Parser/Fortran90Spec.hs +0/−590
- test/Language/Fortran/Parser/Fortran95Spec.hs +0/−660
- test/Language/Fortran/Parser/Free/Common.hs +87/−0
- test/Language/Fortran/Parser/Free/Fortran2003Spec.hs +176/−0
- test/Language/Fortran/Parser/Free/Fortran2008Spec.hs +8/−0
- test/Language/Fortran/Parser/Free/Fortran90Spec.hs +586/−0
- test/Language/Fortran/Parser/Free/Fortran95Spec.hs +655/−0
- test/Language/Fortran/Parser/Free/LexerSpec.hs +383/−0
- test/Language/Fortran/Parser/FreeFormCommon.hs +0/−68
- test/Language/Fortran/Parser/MonadSpec.hs +91/−0
- test/Language/Fortran/Parser/UtilsSpec.hs +0/−29
- test/Language/Fortran/ParserMonadSpec.hs +0/−92
- test/Language/Fortran/PrettyPrintSpec.hs +1/−2
- test/Language/Fortran/Transformation/Disambiguation/FunctionSpec.hs +21/−14
- test/Language/Fortran/Transformation/GroupingSpec.hs +28/−21
- test/Language/Fortran/Util/FirstParameterSpec.hs +0/−4
- test/Language/Fortran/Util/SecondParameterSpec.hs +0/−4
- test/TestUtil.hs +13/−8
CHANGELOG.md view
@@ -1,3 +1,14 @@+### 0.9.0 (Feb 14, 2022)+ * Restructure parsing-related modules for code deduplication and better user+ experience.+ * Now all user-facing parsers and the combinators to create them are in a+ single module at `Language.Fortran.Parser`.+ * The Happy parsers have fewer dependencies, so should no longer require a+ recompile due to apparently unrelated changes.+ * Remove some deprecated shims (from the restructured modules).+ * Merge fortran-src-extras `Language.Fortran.Extras.ModFiles.Extras` module+ into `Language.Fortran.Util.ModFile`.+ ### 0.8.0 (Jan 04, 2022) * Merge declarator constructors. Now you differentiate between array and scalar declarators by looking at the relevant field. See
+ app/Main.hs view
@@ -0,0 +1,469 @@+{-# LANGUAGE ScopedTypeVariables, OverloadedStrings #-}+{-# OPTIONS_GHC -Wno-orphans #-}++module Main ( main ) where++import Prelude hiding (readFile, mod)+import qualified Data.ByteString.Char8 as B+import qualified Data.ByteString.Lazy.Char8 as LB++import Text.PrettyPrint (render)++import System.Console.GetOpt+import System.IO+import System.Environment+import System.Directory+import System.FilePath+import Text.PrettyPrint.GenericPretty (pp, pretty, Out)+import Text.Read (readMaybe)+import Data.List (sortBy, intercalate, isSuffixOf)+import Data.Ord (comparing)+import Data.Char (toLower)+import Data.Maybe (listToMaybe, fromMaybe, maybeToList)+import Data.Data+import Data.Generics.Uniplate.Data+import Data.Graph.Inductive hiding (trc, mf, version)+import Data.Either.Combinators ( fromRight' )++import qualified Data.IntMap as IM+import qualified Data.Map as M+import Control.Monad+import Text.Printf++import Language.Fortran.Parser+import Language.Fortran.Version+import Language.Fortran.Util.ModFile+import Language.Fortran.Util.Position+import Language.Fortran.Util.Files+import Language.Fortran.PrettyPrint+import Language.Fortran.Analysis+import Language.Fortran.AST+import Language.Fortran.Analysis.Types+import Language.Fortran.Analysis.ModGraph+import Language.Fortran.Analysis.BBlocks+import Language.Fortran.Analysis.DataFlow+import Language.Fortran.Analysis.Renaming+import qualified Language.Fortran.Parser as Parser+import qualified Language.Fortran.Parser.Fixed.Lexer as Fixed+import qualified Language.Fortran.Parser.Free.Lexer as Free++programName :: String+programName = "fortran-src"++main :: IO ()+main = do+ args <- getArgs+ (opts, parsedArgs) <- compileArgs args+ case (parsedArgs, action opts) of+ (paths, ShowMakeGraph) -> do+ paths' <- expandDirs paths+ mg <- genModGraph (fortranVersion opts) (includeDirs opts) paths'+ putStrLn $ modGraphToDOT mg+ -- make: construct a build-dep graph and follow it+ (paths, Make) -> do+ let mvers = fortranVersion opts+ paths' <- expandDirs paths+ -- Build the graph of module dependencies+ mg0 <- genModGraph mvers (includeDirs opts) paths'+ -- Start the list of mods with those from the command line+ mods0 <- decodeModFiles' $ includeDirs opts+ -- Loop through the dependency graph until it is empty+ let loop mg mods+ | nxt <- takeNextMods mg+ , not (null nxt) = do+ let fnPaths = [ fn | (_, Just (MOFile fn)) <- nxt ]+ newMods <- fmap concat . forM fnPaths $ \ fnPath -> do+ tsStatus <- checkTimestamps fnPath+ case tsStatus of+ NoSuchFile -> do+ putStr $ "Does not exist: " ++ fnPath+ pure [emptyModFile]+ ModFileExists modPath -> do+ putStrLn $ "Loading mod file " ++ modPath ++ "."+ decodeOneModFile modPath+ CompileFile -> do+ putStr $ "Summarising " ++ fnPath ++ "..."+ mod <- compileFileToMod mvers mods fnPath Nothing+ putStrLn "done"+ pure [mod]++ let ns = map fst nxt+ let mg' = delModNodes ns mg+ loop mg' $ newMods ++ mods+ loop _ mods = pure mods++ allMods <- loop mg0 mods0+ case outputFile opts of+ Nothing -> pure ()+ Just f -> LB.writeFile f $ encodeModFile allMods++ (paths, Compile) -> do+ mods <- decodeModFiles' $ includeDirs opts+ mapM_ (\ p -> compileFileToMod (fortranVersion opts) mods p (outputFile opts)) paths+ (path:_, actionOpt) -> do+ contents <- flexReadFile path+ mods <- decodeModFiles' $ includeDirs opts+ let version = fromMaybe (deduceFortranVersion path) (fortranVersion opts)+ parsedPF = fromRight' $ (Parser.byVerWithMods mods version) path contents+ outfmt = outputFormat opts+ mmap = combinedModuleMap mods+ tenv = combinedTypeEnv mods+ pvm = combinedParamVarMap mods++ let runTypes = analyseAndCheckTypesWithEnv tenv . analyseRenamesWithModuleMap mmap . initAnalysis+ let runRenamer = stripAnalysis . rename . analyseRenamesWithModuleMap mmap . initAnalysis+ let runBBlocks pf = showBBlocks pf' ++ "\n\n" ++ showDataFlow pf'+ where pf' = analyseParameterVars pvm . analyseBBlocks . analyseRenamesWithModuleMap mmap . initAnalysis $ pf+ let runSuperGraph pf | outfmt == DOT = superBBGrToDOT sgr+ | otherwise = superGraphDataFlow pf' sgr+ where pf' = analyseParameterVars pvm . analyseBBlocks . analyseRenamesWithModuleMap mmap . initAnalysis $ pf+ bbm = genBBlockMap pf'+ sgr = genSuperBBGr bbm+ let findBlockPU pf astBlockId = listToMaybe+ [ pu | pu <- universeBi pf :: [ProgramUnit (Analysis A0)]+ , bbgr <- maybeToList (bBlocks (getAnnotation pu))+ , b <- concatMap snd $ labNodes (bbgrGr bbgr)+ , insLabel (getAnnotation b) == Just astBlockId ]+ case actionOpt of+ Lex | version `elem` [ Fortran66, Fortran77, Fortran77Extended, Fortran77Legacy ] ->+ print $ Parser.collectTokens Fixed.lexer' $ initParseStateFixed "<unknown>" version contents+ Lex | version `elem` [Fortran90, Fortran2003, Fortran2008] ->+ print $ Parser.collectTokens Free.lexer' $ initParseStateFree "<unknown>" version contents+ Lex -> ioError $ userError $ usageInfo programName options+ Parse -> pp parsedPF+ Typecheck -> let (pf, _, errs) = runTypes parsedPF in+ printTypeErrors errs >> printTypes (extractTypeEnv pf)+ Rename -> pp $ runRenamer parsedPF+ BBlocks -> putStrLn $ runBBlocks parsedPF+ SuperGraph -> putStrLn $ runSuperGraph parsedPF+ Reprint ->+ let prettyContents = render . flip (pprint version) (Just 0) $ parsedPF+ in putStrLn $+ if useContinuationReformatter opts+ then reformatMixedFormInsertContinuations prettyContents+ else prettyContents+ DumpModFile -> do+ let path' = if modFileSuffix `isSuffixOf` path then path else path <.> modFileSuffix+ contents' <- LB.readFile path'+ case decodeModFile contents' of+ Left msg -> putStrLn $ "Error: " ++ msg+ Right mfs -> forM_ mfs $ \ mf ->+ putStrLn $ "Filename: " ++ moduleFilename mf +++ "\n\nStringMap:\n" ++ showStringMap (combinedStringMap [mf]) +++ "\n\nModuleMap:\n" ++ showModuleMap (combinedModuleMap [mf]) +++ "\n\nDeclMap:\n" ++ showGenericMap (combinedDeclMap [mf]) +++ "\n\nTypeEnv:\n" ++ showTypes (combinedTypeEnv [mf]) +++ "\n\nParamVarMap:\n" ++ showGenericMap (combinedParamVarMap [mf]) +++ "\n\nOther Data Labels: " ++ show (getLabelsModFileData mf)+ ShowFlows isFrom isSuper astBlockId -> do+ let pf = analyseParameterVars pvm .+ analyseBBlocks .+ analyseRenamesWithModuleMap mmap .+ initAnalysis $ parsedPF+ let bbm = genBBlockMap pf+ case (isSuper, findBlockPU pf astBlockId) of+ (False, Nothing) -> fail "Couldn't find given AST block ID number."+ (False, Just pu)+ | Just bbgr <- M.lookup (puName pu) bbm ->+ putStrLn $ showFlowsDOT pf bbgr astBlockId isFrom+ | otherwise -> do+ print $ M.keys bbm+ fail $ "Internal error: Program Unit " ++ show (puName pu) ++ " is lacking a basic block graph."+ (True, _) -> do+ let sgr = genSuperBBGr bbm+ putStrLn $ showFlowsDOT pf (superBBGrGraph sgr) astBlockId isFrom+ ShowBlocks mlinenum -> do+ let pf = analyseBBlocks .+ analyseRenamesWithModuleMap mmap .+ initAnalysis $ parsedPF+ let f :: ([ASTBlockNode], Int) -> ([ASTBlockNode], Int) -> ([ASTBlockNode], Int)+ f (nodes1, len1) (nodes2, len2)+ | len1 < len2 = (nodes1, len1)+ | len2 < len1 = (nodes2, len2)+ | otherwise = (nodes1 ++ nodes2, len1)+ let lineMap :: IM.IntMap ([ASTBlockNode], Int) -- ([list of IDs], line-distance of span)+ lineMap = IM.fromListWith f [+ (l, ([i], lineDistance ss))+ | b <- universeBi pf :: [Block (Analysis A0)]+ , i <- maybeToList . insLabel $ getAnnotation b+ , let ss = getSpan b+ , l <- spannedLines ss+ ]+ case mlinenum of+ Just l -> putStrLn . unwords . map show $ fromMaybe [] (fst <$> IM.lookup l lineMap)+ Nothing -> do+ let lineBs = B.lines contents+ let maxLen = maximum (0:map B.length lineBs)+ forM_ (zip lineBs [1..]) $ \ (line, l) -> do+ let nodeIDs = fromMaybe [] (fst <$> IM.lookup l lineMap)+ let nodeStr = B.intercalate "," (map (B.pack . ('B':) . show) nodeIDs)+ let suffix | null nodeIDs = ""+ | otherwise = B.replicate (maxLen - B.length line + 1) ' ' <> "!" <> nodeStr+ B.putStrLn $ line <> suffix+ _ -> fail $ usageInfo programName options+ _ -> fail $ usageInfo programName options+++-- | Expand all paths that are directories into a list of Fortran+-- files from a recursive directory listing.+expandDirs :: [FilePath] -> IO [FilePath]+expandDirs = fmap concat . mapM each+ where+ each path = do+ isDir <- doesDirectoryExist path+ if isDir+ then listFortranFiles path+ else pure [path]++-- | Get a list of Fortran files under the given directory.+listFortranFiles :: FilePath -> IO [FilePath]+listFortranFiles dir = filter isFortran <$> listDirectoryRecursively dir+ where+ -- | True if the file has a valid fortran extension.+ isFortran :: FilePath -> Bool+ isFortran x = map toLower (takeExtension x) `elem` exts+ where exts = [".f", ".f90", ".f77", ".f03"]++listDirectoryRecursively :: FilePath -> IO [FilePath]+listDirectoryRecursively dir = listDirectoryRec dir ""+ where+ listDirectoryRec :: FilePath -> FilePath -> IO [FilePath]+ listDirectoryRec d f = do+ let fullPath = d </> f+ isDir <- doesDirectoryExist fullPath+ if isDir+ then do+ conts <- listDirectory fullPath+ concat <$> mapM (listDirectoryRec fullPath) conts+ else pure [fullPath]++compileFileToMod :: Maybe FortranVersion -> ModFiles -> FilePath -> Maybe FilePath -> IO ModFile+compileFileToMod mvers mods path moutfile = do+ contents <- flexReadFile path+ let version = fromMaybe (deduceFortranVersion path) mvers+ mmap = combinedModuleMap mods+ tenv = combinedTypeEnv mods+ runCompile = genModFile . fst . analyseTypesWithEnv tenv . analyseRenamesWithModuleMap mmap . initAnalysis+ parsedPF = fromRight' $ (Parser.byVerWithMods mods version) path contents+ mod = runCompile parsedPF+ fspath = path -<.> modFileSuffix `fromMaybe` moutfile+ LB.writeFile fspath $ encodeModFile [mod]+ return mod++decodeOneModFile :: FilePath -> IO ModFiles+decodeOneModFile path = do+ contents <- LB.readFile path+ case decodeModFile contents of+ Left msg -> do+ hPutStrLn stderr $ path ++ ": Error: " ++ msg+ return []+ Right modFiles -> do+ hPutStrLn stderr $ path ++ ": successfully parsed summary file."+ return modFiles++-- TODO almost replicated at Analysis.DataFlow.showDataFlow+superGraphDataFlow :: forall a. (Out a, Data a) => ProgramFile (Analysis a) -> SuperBBGr (Analysis a) -> String+superGraphDataFlow pf sgr = showBBGr (bbgrMap (nmap (map (fmap insLabel))) gr') ++ "\n\n" ++ replicate 50 '-' ++ "\n\n" +++ show entries ++ "\n\n" ++ replicate 50 '-' ++ "\n\n" +++ dfStr gr'+ where+ gr' = superBBGrGraph sgr+ entries = superBBGrEntries sgr+ dfStr gr = (\ (l, x) -> '\n':l ++ ": " ++ x) =<< [+ ("callMap", show cm)+ , ("entries", show (bbgrEntries gr))+ , ("exits", show (bbgrExits gr))+ , ("postOrder", show (postOrder gr))+ , ("revPostOrder", show (revPostOrder gr))+ , ("revPreOrder", show (revPreOrder gr))+ , ("dominators", show (dominators gr))+ , ("iDominators", show (iDominators gr))+ , ("defMap", show dm)+ , ("lva", show (IM.toList $ lva gr))+ , ("rd", show (IM.toList rDefs))+ , ("backEdges", show bedges)+ , ("topsort", show (topsort $ bbgrGr gr))+ , ("scc ", show (scc $ bbgrGr gr))+ , ("loopNodes", show (loopNodes bedges $ bbgrGr gr))+ , ("duMap", show (genDUMap bm dm gr rDefs))+ , ("udMap", show (genUDMap bm dm gr rDefs))+ , ("flowsTo", show (edges flTo))+ , ("varFlowsTo", show (genVarFlowsToMap dm flTo))+ , ("ivMap", show (genInductionVarMap bedges gr))+ , ("blockMap", unlines [ "AST-block " ++ show i ++ ":\n" ++ pretty b | (i, b) <- IM.toList bm ])+ , ("derivedInd", unlines [ "Expression " ++ show i ++ " (IE: " ++ show ie ++ "):\n" ++ pretty e+ | e <- universeBi bm :: [Expression (Analysis a)]+ , i <- maybeToList (insLabel (getAnnotation e))+ , let ie = IM.lookup i diMap ])+ , ("constExpMap", show (genConstExpMap pf))+ ] where+ bedges = genBackEdgeMap (dominators gr) $ bbgrGr gr+ flTo = genFlowsToGraph bm dm gr rDefs+ rDefs = rd gr+ diMap = genDerivedInductionMap bedges gr+ lva = liveVariableAnalysis+ bm = genBlockMap pf+ dm = genDefMap bm+ rd = reachingDefinitions dm+ cm = genCallMap pf++showGenericMap :: (Show a, Show b) => M.Map a b -> String+showGenericMap = unlines . map (\ (k, v) -> show k ++ " : " ++ show v) . M.toList+showStringMap :: StringMap -> String+showStringMap = showGenericMap+showModuleMap :: ModuleMap -> String+showModuleMap = concatMap (\ (n, m) -> show n ++ ":\n" ++ (unlines . map (" "++) . lines . showGenericMap $ m)) . M.toList+showTypes :: TypeEnv -> String+showTypes tenv =+ flip concatMap (M.toList tenv) $+ \ (name, IDType { idVType = vt, idCType = ct }) ->+ printf "%s\t\t%s %s\n" name (drop 1 $ maybe " -" show vt) (drop 2 $ maybe " " show ct)+printTypes :: TypeEnv -> IO ()+printTypes = putStrLn . showTypes+showTypeErrors :: [TypeError] -> String+showTypeErrors errs = unlines [ show ss ++ ": " ++ msg | (msg, ss) <- sortBy (comparing snd) errs ]+printTypeErrors :: [TypeError] -> IO ()+printTypeErrors = putStrLn . showTypeErrors++data Action+ = Lex | Parse | Typecheck | Rename | BBlocks | SuperGraph | Reprint | DumpModFile | Compile+ | ShowFlows Bool Bool Int | ShowBlocks (Maybe Int) | ShowMakeGraph | Make+ deriving Eq++instance Read Action where+ readsPrec _ value =+ let options' = [ ("lex", Lex) , ("parse", Parse) ] in+ tryTypes options'+ where+ tryTypes [] = []+ tryTypes ((attempt,result):xs) =+ if map toLower value == attempt then [(result, "")] else tryTypes xs++data OutputFormat = Default | DOT deriving Eq++data Options = Options+ { fortranVersion :: Maybe FortranVersion+ , action :: Action+ , outputFormat :: OutputFormat+ , outputFile :: Maybe FilePath+ , includeDirs :: [String]+ , useContinuationReformatter :: Bool+ }++initOptions :: Options+initOptions = Options Nothing Parse Default Nothing [] False++options :: [OptDescr (Options -> Options)]+options =+ [ Option ['v','F']+ ["fortranVersion"]+ (ReqArg (\v opts -> opts { fortranVersion = selectFortranVersion v }) "VERSION")+ "Fortran version to use, format: Fortran[66/77/77Legacy/77Extended/90]"+ , Option ['a']+ ["action"]+ (ReqArg (\a opts -> opts { action = read a }) "ACTION")+ "lex or parse action"+ , Option ['t']+ ["typecheck"]+ (NoArg $ \ opts -> opts { action = Typecheck })+ "parse and run typechecker"+ , Option ['R']+ ["rename"]+ (NoArg $ \ opts -> opts { action = Rename })+ "parse and rename variables"+ , Option ['B']+ ["bblocks"]+ (NoArg $ \ opts -> opts { action = BBlocks })+ "analyse basic blocks"+ , Option ['S']+ ["supergraph"]+ (NoArg $ \ opts -> opts { action = SuperGraph })+ "analyse super graph of basic blocks"+ , Option ['r']+ ["reprint"]+ (NoArg $ \ opts -> opts { action = Reprint })+ "Parse and output using pretty printer"+ , Option []+ ["split-long"]+ (NoArg $ \ opts -> opts { useContinuationReformatter = True })+ "when using pretty printer, split long lines via continuations"+ , Option []+ ["dot"]+ (NoArg $ \ opts -> opts { outputFormat = DOT })+ "output graphs in GraphViz DOT format"+ , Option []+ ["dump-mod-file"]+ (NoArg $ \ opts -> opts { action = DumpModFile })+ "dump the information contained within mod files"+ , Option ['I']+ ["include-dir"]+ (ReqArg (\ d opts -> opts { includeDirs = d:includeDirs opts }) "DIR")+ "directory to search for precompiled 'mod files'"+ , Option ['c']+ ["summarise", "compile-mod"]+ (NoArg $ \ opts -> opts { action = Compile })+ "build an .fsmod file from the input"+ , Option ['o']+ ["output-file"]+ (ReqArg (\ f opts -> opts { outputFile = Just f }) "FILE")+ "name of output file (e.g. name of generated fsmod file)"+ , Option []+ ["make-mods", "make"]+ (NoArg $ \ opts -> opts { action = Make })+ "determine dependency order of modules and automatically build .fsmod files"+ , Option []+ ["show-make-graph"]+ (NoArg $ \ opts -> opts { action = ShowMakeGraph })+ "dump a graph showing the build structure of modules"+ , Option []+ ["show-block-numbers"]+ (OptArg (\a opts -> opts { action = ShowBlocks (a >>= readMaybe) }+ ) "LINE-NUM")+ "Show the corresponding AST-block identifier number next to every line of code."+ , Option []+ ["show-flows-to"]+ (ReqArg (\a opts -> case a of s:num | toLower s == 's' -> opts { action = ShowFlows False True (read num) }+ b:num | toLower b == 'b' -> opts { action = ShowFlows False False (read num) }+ num -> opts { action = ShowFlows False False (read num) }+ ) "AST-BLOCK-ID")+ "dump a graph showing flows-to information from the given AST-block ID; prefix with 's' for supergraph"+ , Option []+ ["show-flows-from"]+ (ReqArg (\a opts -> case a of s:num | toLower s == 's' -> opts { action = ShowFlows True True (read num) }+ b:num | toLower b == 'b' -> opts { action = ShowFlows True False (read num) }+ num -> opts { action = ShowFlows True False (read num) }+ ) "AST-BLOCK-ID")+ "dump a graph showing flows-from information from the given AST-block ID; prefix with 's' for supergraph"+ ]++compileArgs :: [ String ] -> IO (Options, [ String ])+compileArgs args =+ case getOpt Permute options args of+ (o, n, []) -> return (foldl (flip id) initOptions o, n)+ (_, _, errors) -> ioError $ userError $ concat errors ++ usageInfo header options+ where+ header = "Usage: " ++ programName ++ " [OPTION...] <file...>"++instance {-# OVERLAPPING #-} Show [ Fixed.Token ] where+ show = unlines . lines'+ where+ lines' [] = []+ lines' xs =+ let (x, xs') = break isNewline xs+ in case xs' of+ (nl@(Fixed.TNewline _):xs'') -> ('\t' : (intercalate ", " . map show $ x ++ [nl])) : lines' xs''+ xs'' -> [ show xs'' ]+ isNewline (Fixed.TNewline _) = True+ isNewline _ = False++instance {-# OVERLAPPING #-} Show [ Free.Token ] where+ show = unlines . lines'+ where+ lines' [] = []+ lines' xs =+ let (x, xs') = break isNewline xs+ in case xs' of+ (nl@(Free.TNewline _):xs'') -> ('\t' : (intercalate ", " . map show $ x ++ [nl])) : lines' xs''+ xs'' -> [ show xs'' ]+ isNewline (Free.TNewline _) = True+ isNewline _ = False
fortran-src.cabal view
@@ -5,7 +5,7 @@ -- see: https://github.com/sol/hpack name: fortran-src-version: 0.8.0+version: 0.9.0 synopsis: Parsers and analyses for Fortran standards 66, 77, 90, 95 and 2003 (partial). description: Provides lexing, parsing, and basic analyses of Fortran code covering standards: FORTRAN 66, FORTRAN 77, Fortran 90, Fortran 95, Fortran 2003 (partial) and some legacy extensions. Includes data flow and basic block analysis, a renamer, and type analysis. For example usage, see the @<https://hackage.haskell.org/package/camfort CamFort>@ project, which uses fortran-src as its front end. category: Language@@ -62,46 +62,67 @@ library exposed-modules:- Language.Fortran.Analysis.SemanticTypes Language.Fortran.Analysis- Language.Fortran.Analysis.Renaming- Language.Fortran.Analysis.ModGraph- Language.Fortran.Analysis.Types Language.Fortran.Analysis.BBlocks Language.Fortran.Analysis.DataFlow+ Language.Fortran.Analysis.ModGraph+ Language.Fortran.Analysis.Renaming+ Language.Fortran.Analysis.SemanticTypes+ Language.Fortran.Analysis.Types Language.Fortran.AST Language.Fortran.AST.AList- Language.Fortran.AST.RealLit Language.Fortran.AST.Boz- Language.Fortran.Version- Language.Fortran.LValue+ Language.Fortran.AST.RealLit Language.Fortran.Intrinsics- Language.Fortran.Lexer.FixedForm- Language.Fortran.Lexer.FixedForm.Utils- Language.Fortran.Lexer.FreeForm- Language.Fortran.ParserMonad- Language.Fortran.Parser.Any- Language.Fortran.Parser.Fortran66- Language.Fortran.Parser.Fortran77- Language.Fortran.Parser.Fortran90- Language.Fortran.Parser.Fortran95- Language.Fortran.Parser.Fortran2003- Language.Fortran.Parser.Utils+ Language.Fortran.LValue+ Language.Fortran.Parser+ Language.Fortran.Parser.Fixed.Fortran66+ Language.Fortran.Parser.Fixed.Fortran77+ Language.Fortran.Parser.Fixed.Lexer+ Language.Fortran.Parser.Fixed.Utils+ Language.Fortran.Parser.Free.Fortran2003+ Language.Fortran.Parser.Free.Fortran90+ Language.Fortran.Parser.Free.Fortran95+ Language.Fortran.Parser.Free.Lexer+ Language.Fortran.Parser.Free.Utils+ Language.Fortran.Parser.LexerUtils+ Language.Fortran.Parser.Monad Language.Fortran.PrettyPrint+ Language.Fortran.Rewriter+ Language.Fortran.Rewriter.Internal Language.Fortran.Transformation.Disambiguation.Function Language.Fortran.Transformation.Disambiguation.Intrinsic Language.Fortran.Transformation.Grouping- Language.Fortran.Transformation.TransformMonad- Language.Fortran.Transformer- Language.Fortran.Util.Position+ Language.Fortran.Transformation.Monad+ Language.Fortran.Util.Files Language.Fortran.Util.FirstParameter- Language.Fortran.Util.SecondParameter Language.Fortran.Util.ModFile- Language.Fortran.Util.Files- Language.Fortran.Rewriter- Language.Fortran.Rewriter.Internal+ Language.Fortran.Util.Position+ Language.Fortran.Util.SecondParameter+ Language.Fortran.Version+ other-modules:+ Paths_fortran_src hs-source-dirs: src+ default-extensions:+ EmptyCase+ FlexibleContexts+ FlexibleInstances+ InstanceSigs+ MultiParamTypeClasses+ PolyKinds+ LambdaCase+ DerivingStrategies+ StandaloneDeriving+ DeriveAnyClass+ DeriveGeneric+ DeriveDataTypeable+ DeriveFunctor+ DeriveFoldable+ DeriveTraversable+ DeriveLift+ BangPatterns+ TupleSections ghc-options: -Wall -fno-warn-tabs build-tools: alex >=3.1@@ -115,6 +136,7 @@ , containers >=0.5 && <0.7 , deepseq ==1.4.* , directory >=1.2 && <2+ , either >=5.0.1.1 && <5.1 , fgl ==5.* , filepath ==1.4.* , mtl >=2.2 && <3@@ -125,9 +147,30 @@ default-language: Haskell2010 executable fortran-src- main-is: src/Main.hs+ main-is: Main.hs other-modules: Paths_fortran_src+ hs-source-dirs:+ app+ default-extensions:+ EmptyCase+ FlexibleContexts+ FlexibleInstances+ InstanceSigs+ MultiParamTypeClasses+ PolyKinds+ LambdaCase+ DerivingStrategies+ StandaloneDeriving+ DeriveAnyClass+ DeriveGeneric+ DeriveDataTypeable+ DeriveFunctor+ DeriveFoldable+ DeriveTraversable+ DeriveLift+ BangPatterns+ TupleSections ghc-options: -Wall -fno-warn-tabs build-depends: GenericPretty >=1.2.2 && <2@@ -138,6 +181,7 @@ , containers >=0.5 && <0.7 , deepseq ==1.4.* , directory >=1.2 && <2+ , either >=5.0.1.1 && <5.1 , fgl ==5.* , filepath ==1.4.* , fortran-src@@ -160,18 +204,17 @@ Language.Fortran.AnalysisSpec Language.Fortran.AST.BozSpec Language.Fortran.AST.RealLitSpec- Language.Fortran.Lexer.FixedFormSpec- Language.Fortran.Lexer.FreeFormSpec- Language.Fortran.Parser.Fortran2003Spec- Language.Fortran.Parser.Fortran2008Spec- Language.Fortran.Parser.Fortran66Spec- Language.Fortran.Parser.Fortran77.IncludeSpec- Language.Fortran.Parser.Fortran77.ParserSpec- Language.Fortran.Parser.Fortran90Spec- Language.Fortran.Parser.Fortran95Spec- Language.Fortran.Parser.FreeFormCommon- Language.Fortran.Parser.UtilsSpec- Language.Fortran.ParserMonadSpec+ Language.Fortran.Parser.Fixed.Fortran66Spec+ Language.Fortran.Parser.Fixed.Fortran77.IncludeSpec+ Language.Fortran.Parser.Fixed.Fortran77.ParserSpec+ Language.Fortran.Parser.Fixed.LexerSpec+ Language.Fortran.Parser.Free.Common+ Language.Fortran.Parser.Free.Fortran2003Spec+ Language.Fortran.Parser.Free.Fortran2008Spec+ Language.Fortran.Parser.Free.Fortran90Spec+ Language.Fortran.Parser.Free.Fortran95Spec+ Language.Fortran.Parser.Free.LexerSpec+ Language.Fortran.Parser.MonadSpec Language.Fortran.PrettyPrintSpec Language.Fortran.Rewriter.InternalSpec Language.Fortran.RewriterSpec@@ -183,6 +226,25 @@ Paths_fortran_src hs-source-dirs: test+ default-extensions:+ EmptyCase+ FlexibleContexts+ FlexibleInstances+ InstanceSigs+ MultiParamTypeClasses+ PolyKinds+ LambdaCase+ DerivingStrategies+ StandaloneDeriving+ DeriveAnyClass+ DeriveGeneric+ DeriveDataTypeable+ DeriveFunctor+ DeriveFoldable+ DeriveTraversable+ DeriveLift+ BangPatterns+ TupleSections ghc-options: -Wall build-tool-depends: hspec-discover:hspec-discover@@ -196,6 +258,7 @@ , containers >=0.5 && <0.7 , deepseq ==1.4.* , directory >=1.2 && <2+ , either >=5.0.1.1 && <5.1 , fgl ==5.* , filepath ==1.4.* , fortran-src
src/Language/Fortran/AST.hs view
@@ -1,10 +1,4 @@-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE DeriveDataTypeable #-}-{-# LANGUAGE DeriveGeneric #-}-{-# LANGUAGE DeriveFunctor #-} {-# LANGUAGE DefaultSignatures #-}-{-# LANGUAGE FlexibleContexts #-} -- | --@@ -73,6 +67,9 @@ , ModuleNature(..) , Use(..) , Argument(..)+ , ArgumentExpression(..)+ , argExprNormalize+ , argExtractExpr , Intent(..) , ControlPair(..) , AllocOpt(..)@@ -115,19 +112,17 @@ ) where -import Prelude hiding (init)+import Prelude hiding ( init ) import Language.Fortran.AST.AList import Language.Fortran.AST.RealLit-import Language.Fortran.AST.Boz (Boz)+import Language.Fortran.AST.Boz ( Boz ) import Language.Fortran.Util.Position import Language.Fortran.Util.FirstParameter import Language.Fortran.Util.SecondParameter-import Language.Fortran.Version (FortranVersion(..))+import Language.Fortran.Version import Data.Data-import Data.Generics.Uniplate.Data ()-import Data.Typeable () import Data.Binary import Control.DeepSeq import Text.PrettyPrint.GenericPretty@@ -490,9 +485,22 @@ | UseID a SrcSpan (Expression a) deriving (Eq, Show, Data, Typeable, Generic, Functor) -data Argument a = Argument a SrcSpan (Maybe String) (Expression a)+-- TODO potentially should throw Maybe String into ArgumentExpression too?+data Argument a = Argument a SrcSpan (Maybe String) (ArgumentExpression a) deriving (Eq, Show, Data, Typeable, Generic, Functor) +data ArgumentExpression a+ = ArgExpr (Expression a)+ | ArgExprVar a SrcSpan Name+ deriving (Eq, Show, Data, Typeable, Generic, Functor)++argExprNormalize :: ArgumentExpression a -> Expression a+argExprNormalize = \case ArgExpr e -> e+ ArgExprVar a ss v -> ExpValue a ss (ValVariable v)++argExtractExpr :: Argument a -> Expression a+argExtractExpr (Argument _ _ _ ae) = argExprNormalize ae+ data Attribute a = AttrAllocatable a SrcSpan | AttrAsynchronous a SrcSpan@@ -918,6 +926,7 @@ instance Out Only instance Out ModuleNature instance Out a => Out (Argument a)+instance Out a => Out (ArgumentExpression a) instance Out a => Out (Use a) instance Out a => Out (Attribute a) instance Out Intent@@ -1016,6 +1025,7 @@ instance NFData a => NFData (Selector a) instance NFData a => NFData (ForallHeader a) instance NFData a => NFData (Argument a)+instance NFData a => NFData (ArgumentExpression a) instance NFData a => NFData (Use a) instance NFData a => NFData (Attribute a) instance NFData a => NFData (CommonGroup a)
src/Language/Fortran/AST/AList.hs view
@@ -1,9 +1,3 @@-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE DeriveDataTypeable #-}-{-# LANGUAGE DeriveGeneric #-}-{-# LANGUAGE DeriveFunctor #-}- module Language.Fortran.AST.AList where import Language.Fortran.Util.FirstParameter
src/Language/Fortran/AST/Boz.hs view
@@ -15,9 +15,6 @@ 'Bits' instance. -} -{-# LANGUAGE DerivingStrategies, DeriveDataTypeable, DeriveGeneric, DeriveAnyClass #-}-{-# LANGUAGE LambdaCase #-}- module Language.Fortran.AST.Boz where import GHC.Generics@@ -28,7 +25,6 @@ import qualified Data.List as List import qualified Data.Char as Char import qualified Numeric as Num-import Data.Maybe ( isJust, fromJust ) -- | A Fortran BOZ literal constant. --@@ -44,9 +40,9 @@ deriving anyclass (NFData, Out) data BozPrefix- = BozPrefixB- | BozPrefixO- | BozPrefixZ -- also @x@+ = BozPrefixB -- ^ binary (bitstring)+ | BozPrefixO -- ^ octal+ | BozPrefixZ -- ^ hex (also with prefix @x@) deriving stock (Eq, Show, Generic, Data, Typeable, Ord) deriving anyclass (NFData, Out) @@ -78,24 +74,24 @@ -- @x@ for hexadecimal. prettyBoz :: Boz -> String prettyBoz b = prettyBozPrefix (bozPrefix b) : '\'' : bozString b <> "'"- where prettyBozPrefix = \case- BozPrefixB -> 'b'- BozPrefixO -> 'o'- BozPrefixZ -> 'z'+ where prettyBozPrefix = \case BozPrefixB -> 'b'+ BozPrefixO -> 'o'+ BozPrefixZ -> 'z' -- | Resolve a BOZ constant as a natural (positive integer). -- -- Is actually polymorphic over the output type, but you probably want to -- resolve to 'Integer' or 'Natural' usually.+--+-- We assume the 'Boz' is well-formed, thus don't bother with digit predicates. bozAsNatural :: (Num a, Eq a) => Boz -> a bozAsNatural (Boz pfx str) = runReadS $ parser str where runReadS = fst . head- parser = case pfx of- BozPrefixB -> -- TODO on GHC 9.2, 'Num.readBin'- Num.readInt 2 (isJust . binCharFunc) (fromJust . binCharFunc)- BozPrefixO -> Num.readOct- BozPrefixZ -> Num.readHex- binCharFunc = \case '0' -> Just 0- '1' -> Just 1- _ -> Nothing+ parser = case pfx of BozPrefixB -> Num.readInt 2 (const True) binDigitVal+ -- (on GHC >=9.2, 'Num.readBin')+ BozPrefixO -> Num.readOct+ BozPrefixZ -> Num.readHex+ binDigitVal = \case '0' -> 0+ '1' -> 1+ _ -> error "Language.Fortran.AST.BOZ.bozAsNatural: invalid BOZ string"
src/Language/Fortran/AST/RealLit.hs view
@@ -12,8 +12,7 @@ Haskell literals do not support this.) -} -{-# LANGUAGE DeriveDataTypeable, DeriveGeneric, DeriveAnyClass #-}-{-# LANGUAGE RecordWildCards, LambdaCase #-}+{-# LANGUAGE RecordWildCards #-} module Language.Fortran.AST.RealLit where
src/Language/Fortran/Analysis.hs view
@@ -1,4 +1,4 @@-{-# LANGUAGE ScopedTypeVariables, DeriveDataTypeable, StandaloneDeriving, DeriveGeneric, TupleSections #-}+{-# LANGUAGE ScopedTypeVariables #-} {-# OPTIONS_GHC -Wno-orphans #-} -- |@@ -240,7 +240,7 @@ lhsOfStmt :: Statement a -> [Expression a] lhsOfStmt (StExpressionAssign _ _ e e') = e : onExprs e' lhsOfStmt (StCall _ _ _ (Just aexps)) = filter isLExpr argExps ++ concatMap onExprs argExps- where argExps = map extractExp . aStrip $ aexps+ where argExps = map argExtractExpr . aStrip $ aexps lhsOfStmt s = onExprs s onExprs :: (Data a, Data (c a)) => c a -> [Expression a]@@ -249,8 +249,7 @@ lhsOfExp (ExpFunctionCall _ _ _ (Just aexps)) = fstLvl aexps lhsOfExp _ = [] - fstLvl = filter isLExpr . map extractExp . aStrip- extractExp (Argument _ _ _ exp) = exp+ fstLvl = filter isLExpr . map argExtractExpr . aStrip -- | Return list of expressions that are not "left-hand-side" of -- assignment statements.@@ -298,7 +297,7 @@ lhsOfStmt (StDeclaration _ _ _ _ decls) = concat [ lhsOfDecls decl | decl <- universeBi decls ] lhsOfStmt (StCall _ _ f@(ExpValue _ _ (ValIntrinsic _)) _) | Just defs <- intrinsicDefs f = defs- lhsOfStmt (StCall _ _ _ (Just aexps)) = concatMap (match'' . extractExp) (aStrip aexps)+ lhsOfStmt (StCall _ _ _ (Just aexps)) = concatMap (match'' . argExtractExpr) (aStrip aexps) lhsOfStmt s = onExprs s lhsOfDecls (Declarator _ _ e _ _ (Just e')) = match' e : onExprs e'@@ -308,10 +307,8 @@ onExprs = concatMap lhsOfExp . universeBi lhsOfExp :: Expression (Analysis a) -> [Name]- lhsOfExp (ExpFunctionCall _ _ _ (Just aexps)) = concatMap (match . extractExp) (aStrip aexps)+ lhsOfExp (ExpFunctionCall _ _ _ (Just aexps)) = concatMap (match . argExtractExpr) (aStrip aexps) lhsOfExp _ = []-- extractExp (Argument _ _ _ exp) = exp -- Match and give the varname for LHS of statement match' v@(ExpValue _ _ ValVariable{}) = varName v
src/Language/Fortran/Analysis/BBlocks.hs view
@@ -1,6 +1,6 @@ -- | Analyse a program file and create basic blocks. -{-# LANGUAGE TupleSections, FlexibleContexts, PatternGuards, ScopedTypeVariables #-}+{-# LANGUAGE ScopedTypeVariables #-} module Language.Fortran.Analysis.BBlocks ( analyseBBlocks, genBBlockMap, showBBGr, showAnalysedBBGr, showBBlocks, bbgrToDOT, BBlockMap, ASTBlockNode, ASTExprNode , genSuperBBGr, SuperBBGr(..), showSuperBBGr, superBBGrToDOT, findLabeledBBlock, showBlock )@@ -428,7 +428,7 @@ createEdges [ (prevN, callN, ()), (callN, nextN, ()) ] perBlock (BlStatement a s l (StCall a' s' cn@ExpValue{} (Just aargs))) = do let a0 = head . initAnalysis $ [prevAnnotation a]- let exps = map extractExp . aStrip $ aargs+ let exps = map argExtractExpr . aStrip $ aargs (prevN, formalN) <- closeBBlock -- create bblock that assigns formal parameters (n[1], n[2], ...)@@ -448,7 +448,8 @@ -- formalN' may differ from formalN when additional bblocks were -- generated by processFunctionCalls. - let dummyArgs = map (Argument a0 s' Nothing) (zipWith formal exps [(1::Integer)..])+ let dummyArgs = map (\e -> Argument a0 s' Nothing (ArgExpr e))+ (zipWith formal exps [(1::Integer)..]) -- create "dummy call" bblock with dummy parameters in the StCall AST-node. addToBBlock . analyseAllLhsVars1 $ BlStatement a s Nothing (StCall a' s' cn (Just $ fromList a0 dummyArgs))@@ -575,7 +576,7 @@ let a0 = head . initAnalysis $ [prevAnnotation a] (prevN, formalN) <- closeBBlock - let exps = map extractExp (fromMaybe [] (aStrip <$> aargs))+ let exps = map argExtractExpr (fromMaybe [] (aStrip <$> aargs)) -- create bblock that assigns formal parameters (fn[1], fn[2], ...) let name i = varName fn ++ "[" ++ show i ++ "]"@@ -587,7 +588,8 @@ (_, dummyCallN) <- closeBBlock let retV = genVar a0 s $ name (0::Integer)- let dummyArgs = map (Argument a0 s' Nothing) (retV:zipWith formal exps [(1::Integer)..])+ let dummyArgs = map (\e -> Argument a0 s' Nothing (ArgExpr e))+ (retV:zipWith formal exps [(1::Integer)..]) -- create "dummy call" bblock with dummy arguments in the StCall AST-node. addToBBlock . analyseAllLhsVars1 $ BlStatement a s Nothing (StCall a' s' fn (Just $ fromList a0 dummyArgs))@@ -610,9 +612,6 @@ , (dummyCallN, returnedN, ()), (returnedN, nextN, ()) ] return temp processFunctionCall e = return e--extractExp :: Argument a -> Expression a-extractExp (Argument _ _ _ exp) = exp -------------------------------------------------- -- Supergraph: all program units in one basic-block graph
src/Language/Fortran/Analysis/DataFlow.hs view
@@ -1,6 +1,6 @@ -- | Dataflow analysis to be applied once basic block analysis is complete. -{-# LANGUAGE FlexibleContexts, PatternGuards, ScopedTypeVariables, TupleSections, DeriveGeneric, DeriveDataTypeable, BangPatterns #-}+{-# LANGUAGE ScopedTypeVariables #-} module Language.Fortran.Analysis.DataFlow ( dominators, iDominators, DomMap, IDomMap , postOrder, revPostOrder, preOrder, revPreOrder, OrderF@@ -30,7 +30,6 @@ import Control.DeepSeq import Control.Arrow ((&&&)) import Text.PrettyPrint.GenericPretty (Out)-import Language.Fortran.Parser.Utils import Language.Fortran.Analysis import Language.Fortran.Analysis.BBlocks (showBlock, ASTBlockNode, ASTExprNode) import Language.Fortran.AST@@ -406,9 +405,7 @@ labelOf = insLabel . getAnnotation doExpr :: Expression (Analysis a) -> Maybe Constant doExpr e = case e of- ExpValue _ _ (ValInteger str _)- | Just i <- readInteger str -> Just . ConstInt $ fromIntegral i- ExpValue _ _ (ValInteger str _) -> Just $ ConstUninterpInt str+ ExpValue _ _ (ValInteger intStr _) -> Just . ConstInt $ read intStr ExpValue _ _ (ValReal r _) -> Just $ ConstUninterpReal (prettyHsRealLit r) -- TODO ExpValue _ _ (ValVariable _) -> getV e -- Recursively seek information about sub-expressions, relying on laziness.@@ -603,8 +600,7 @@ derivedInductionExpr :: Data a => IEFlow -> Expression (Analysis a) -> InductionExpr derivedInductionExpr flow e = case e of v@(ExpValue _ _ (ValVariable _)) -> fromMaybe IETop $ M.lookup (varName v) (ieFlowVars flow)- ExpValue _ _ (ValInteger str _)- | Just i <- readInteger str -> IELinear "" 0 (fromIntegral i)+ ExpValue _ _ (ValInteger intStr _) -> IELinear "" 0 $ read intStr ExpBinary _ _ Addition e1 e2 -> derive e1 `addInductionExprs` derive e2 ExpBinary _ _ Subtraction e1 e2 -> derive e1 `addInductionExprs` negInductionExpr (derive e2) ExpBinary _ _ Multiplication e1 e2 -> derive e1 `mulInductionExprs` derive e2@@ -621,8 +617,7 @@ | otherwise = derivedInductionExprM e' ie <- case e of v@(ExpValue _ _ (ValVariable _)) -> pure . fromMaybe IETop $ M.lookup (varName v) (ieFlowVars flow)- ExpValue _ _ (ValInteger str _)- | Just i <- readInteger str -> pure $ IELinear "" 0 (fromIntegral i)+ ExpValue _ _ (ValInteger intStr _) -> pure $ IELinear "" 0 $ read intStr ExpBinary _ _ Addition e1 e2 -> addInductionExprs <$> derive e1 <*> derive e2 ExpBinary _ _ Subtraction e1 e2 -> addInductionExprs <$> derive e1 <*> (negInductionExpr <$> derive e2) ExpBinary _ _ Multiplication e1 e2 -> mulInductionExprs <$> derive e1 <*> derive e2
src/Language/Fortran/Analysis/ModGraph.hs view
@@ -1,10 +1,16 @@-{-# LANGUAGE DeriveDataTypeable, ScopedTypeVariables, PatternGuards, TupleSections #-}+{-# LANGUAGE ScopedTypeVariables #-} -- | Generate a module use-graph. module Language.Fortran.Analysis.ModGraph (genModGraph, ModGraph(..), ModOrigin(..), modGraphToDOT, takeNextMods, delModNodes) where +import Language.Fortran.AST hiding (setName)+import qualified Language.Fortran.Parser as Parser+import Language.Fortran.Version+import Language.Fortran.Util.ModFile+import Language.Fortran.Util.Files+ import Prelude hiding (mod) import Control.Monad import Control.Monad.State.Strict@@ -12,16 +18,8 @@ import Data.Generics.Uniplate.Data import Data.Graph.Inductive hiding (version) import Data.Maybe-import Language.Fortran.AST hiding (setName)-import Language.Fortran.Version (FortranVersion(..), deduceFortranVersion)-import Language.Fortran.Parser.Any (parserWithModFilesVersions)-import Language.Fortran.ParserMonad (fromRight)-import Language.Fortran.Util.ModFile-import Language.Fortran.Util.Files-import qualified Data.ByteString.Lazy.Char8 as LB+import Data.Either.Combinators ( fromRight' ) import qualified Data.Map as M-import System.IO-import System.FilePath -------------------------------------------------- @@ -85,16 +83,16 @@ let iter :: FilePath -> ModGrapher () iter path = do contents <- liftIO $ flexReadFile path- let version = fromMaybe (deduceFortranVersion path) mversion- let parserF0 = parserWithModFilesVersions version- let parserF m b s = fromRight (parserF0 m b s) fileMods <- liftIO $ decodeModFiles includeDirs- let mods = map snd fileMods+ let version = fromMaybe (deduceFortranVersion path) mversion+ mods = map snd fileMods+ parserF0 = Parser.byVerWithMods mods version+ parserF fn bs = fromRight' $ parserF0 fn bs forM_ fileMods $ \ (fileName, mod) -> do forM_ [ name | Named name <- M.keys (combinedModuleMap [mod]) ] $ \ name -> do _ <- maybeAddModName name . Just $ MOFSMod fileName pure ()- let pf = parserF mods contents path+ let pf = parserF path contents mapM_ (perModule path) (childrenBi pf :: [ProgramUnit ()]) pure () execStateT (mapM_ iter paths) modGraph0@@ -123,24 +121,3 @@ delModNodes ns mg@ModGraph { mgGraph = gr } = mg' where mg' = mg { mgGraph = delNodes ns gr }------------------------------------------------------decodeModFiles :: [FilePath] -> IO [(FilePath, ModFile)]-decodeModFiles = foldM (\ modFiles d -> do- -- Figure out the camfort mod files and parse them.- modFileNames <- filter isModFile `fmap` getDirContents d- addedModFiles <- fmap concat . forM modFileNames $ \ modFileName -> do- contents <- LB.readFile (d </> modFileName)- case decodeModFile contents of- Left msg -> do- hPutStrLn stderr $ modFileName ++ ": Error: " ++ msg- return [(modFileName, emptyModFile)]- Right mods -> do- hPutStrLn stderr $ modFileName ++ ": successfully parsed precompiled file."- return $ map (modFileName,) mods- return $ addedModFiles ++ modFiles- ) [] -- can't use emptyModFiles--isModFile :: FilePath -> Bool-isModFile = (== modFileSuffix) . takeExtension
src/Language/Fortran/Analysis/Renaming.hs view
@@ -1,4 +1,4 @@-{-# LANGUAGE ScopedTypeVariables, PatternGuards, TupleSections #-}+{-# LANGUAGE ScopedTypeVariables #-} -- | -- Analyse variables/function names and produce unique names that can@@ -14,7 +14,7 @@ import Language.Fortran.AST hiding (fromList) import Language.Fortran.Intrinsics import Language.Fortran.Analysis-import Language.Fortran.ParserMonad (FortranVersion(..))+import Language.Fortran.Version import Prelude hiding (lookup) import Data.Maybe (mapMaybe, fromMaybe)
src/Language/Fortran/Analysis/SemanticTypes.hs view
@@ -1,7 +1,4 @@-{-# LANGUAGE DeriveDataTypeable #-}-{-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE LambdaCase #-} {-# LANGUAGE OverloadedStrings #-} module Language.Fortran.Analysis.SemanticTypes where
src/Language/Fortran/Analysis/Types.hs view
@@ -1,6 +1,4 @@ {-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE LambdaCase #-}-{-# LANGUAGE FlexibleContexts #-} module Language.Fortran.Analysis.Types ( analyseTypes@@ -428,8 +426,8 @@ ITLogical -> wrapBaseType TypeLogical ITCharacter -> wrapBaseType TypeCharacter ITParam i- | length params >= i, Argument _ _ _ e <- params !! (i-1)- -> return $ idVType =<< getIDType e+ | length params >= i, Argument _ _ _ ae <- params !! (i-1)+ -> return $ idVType =<< getIDType (argExprNormalize ae) | otherwise -> typeError ("Invalid parameter list to intrinsic '" ++ n ++ "'") ss >> return Nothing case mst of Nothing -> return emptyType
src/Language/Fortran/Intrinsics.hs view
@@ -1,6 +1,3 @@-{-# LANGUAGE DeriveDataTypeable #-}-{-# LANGUAGE DeriveGeneric #-}- module Language.Fortran.Intrinsics ( getVersionIntrinsics, getIntrinsicReturnType, getIntrinsicNames, getIntrinsicDefsUses, isIntrinsic , IntrinsicType(..), IntrinsicsTable, allIntrinsics )@@ -10,7 +7,7 @@ import Data.Data import Data.List import GHC.Generics (Generic)-import Language.Fortran.ParserMonad (FortranVersion(..))+import Language.Fortran.Version data IntrinsicType = ITReal | ITInteger | ITComplex | ITDouble | ITLogical | ITCharacter | ITParam Int
src/Language/Fortran/LValue.hs view
@@ -1,9 +1,3 @@-{-# LANGUAGE DeriveDataTypeable #-}-{-# LANGUAGE DeriveFunctor #-}-{-# LANGUAGE DeriveGeneric #-}-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE MultiParamTypeClasses #-}- module Language.Fortran.LValue where import Prelude hiding (exp)
− src/Language/Fortran/Lexer/FixedForm.x
@@ -1,1153 +0,0 @@--- -*- Mode: Haskell -*--{-{-# LANGUAGE BangPatterns #-}-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE DeriveGeneric #-}-{-# LANGUAGE DeriveDataTypeable #-}-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE UndecidableInstances #-}--module Language.Fortran.Lexer.FixedForm- ( lexer, initParseState, collectFixedTokens, collectFixedTokensSafe- , Token(..), LexAction, AlexInput(..), lexemeMatch, lexN- ) where--import Data.Word (Word8)-import Data.Char (toLower, ord, isDigit)-import Data.List (isPrefixOf)-import Data.Maybe (fromJust, isNothing, isJust)-import Data.Data-import qualified Data.Bits-import qualified Data.ByteString.Char8 as B--import Control.Monad.State--import GHC.Generics--import Language.Fortran.ParserMonad---import Language.Fortran.Version (required when ParserMonad stops exporting it)-import Language.Fortran.Util.FirstParameter-import Language.Fortran.Util.Position-import Language.Fortran.Parser.Utils (readInteger)-import Language.Fortran.AST.Boz--}--$digit = 0-9-$bit = 0-1-$octalDigit = 0-7-$hexDigit = [a-f $digit]--$hash = [\#]--@binary = b\'$bit+\' | \'$bit+\'b-@octal = o\'$octalDigit+\' | \'$octalDigit+\'o-@hex = [xz]\'$hexDigit+\' | \'$hexDigit+\'[xz]--$letter = a-z-$alphanumeric = [$letter $digit]-$alphanumericExtended = [$letter $digit \_]-$special = [\ \=\+\-\*\/\(\)\,\.\$]---- This should really be 6 characters but there are many standard non-compliant--- programs out there.-@idExtended = $letter $alphanumericExtended{0,9} $alphanumericExtended{0,9} $alphanumericExtended{0,9} $alphanumericExtended?-@id = $letter $alphanumeric{0,5}-@label = $digit{1,5}--@idLegacy = [$letter \_] [$alphanumericExtended \$]*--@datatype = "integer" | "real" | "doubleprecision" | "complex" | "logical"- -- legacy extensions- | "byte"---- Numbers-@integerConst = $digit+-@posIntegerConst = [1-9] $digit*-@bozLiteralConst = (@binary|@octal|@hex)---- For reals-@exponent = [ed] [\+\-]? @integerConst---- For format items-@repeat = @posIntegerConst?-@width = @posIntegerConst--tokens :--- <0> [c!\*d] / { commentP } { lexComment }- "!" / { bangCommentP &&& legacy77P } { lexComment }- <0> @label / { withinLabelColsP } { addSpanAndMatch TLabel }- <0> . / { \_ ai _ _ -> atColP 6 ai } { toSC keyword }- <0> " " ;-- <0> $hash { lexHash }-- <0,st,keyword,iif,assn,doo> \n { resetPar >> toSC 0 >> addSpan TNewline }- <0,st,keyword,iif,assn,doo> \r ;-- <st,keyword,iif,assn,doo> ";" { resetPar >> toSC keyword >> addSpan TNewline }-- <st> "(" { addSpan TLeftPar }- <keyword> "(" / { legacy77P } { addSpan TLeftPar }- <iif> "(" { incPar >> addSpan TLeftPar }- <st> ")" { addSpan TRightPar }- <keyword> ")" / { legacy77P } { typeSCChange >> addSpan TRightPar }- <iif> ")" { maybeToKeyword >> addSpan TRightPar }- <st,iif> "(/" / { formatExtendedP } { addSpan TLeftArrayPar }- <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 }-- <keyword> @id / { idP } { toSC st >> addSpanAndMatch TId }- <keyword> @idExtended / { extendedIdP } { toSC st >> addSpanAndMatch TId }- <keyword> @idLegacy / { legacyIdP } { toSC st >> addSpanAndMatch TId }-- <keyword> "include" / { extended77P } { toSC st >> addSpan TInclude }-- -- Tokens related to procedures and subprograms- <keyword> "program" { toSC st >> addSpan TProgram }- <keyword> "function" / { functionP } { toSC st >> addSpan TFunction }- <keyword> "subroutine" { toSC st >> addSpan TSubroutine }- <keyword> "blockdata" { toSC st >> addSpan TBlockData }- <keyword> "structure" / { legacy77P } { toSC st >> addSpan TStructure }- <keyword> "union" / { legacy77P } { toSC st >> addSpan TUnion }- <keyword> "map" / { legacy77P } { toSC st >> addSpan TMap }- <keyword> "endstructure" / { legacy77P } { toSC st >> addSpan TEndStructure }- <keyword> "endunion" / { legacy77P } { toSC st >> addSpan TEndUnion }- <keyword> "endmap" / { legacy77P } { toSC st >> addSpan TEndMap }- <keyword> "record" / { legacy77P } { toSC st >> addSpan TRecord }- <keyword> "end" { toSC st >> addSpan TEnd }- <keyword> "endprogram" / { legacy77P } { toSC st >> addSpan TEndProgram }- <keyword> "endfunction" / { legacy77P } { toSC st >> addSpan TEndFunction }- <keyword> "endsubroutine" / { legacy77P } { toSC st >> addSpan TEndSubroutine }-- -- Tokens related to assignment statements- <keyword> "assign" { toSC assn >> addSpan TAssign }- <assn> @integerConst { addSpanAndMatch TInt }- <assn> "to" { addSpan TTo }- <assn> @id / { notToP } { addSpanAndMatch TId }- <assn> @idExtended / { notToP &&& extended77P } { addSpanAndMatch TId }- <assn> @idLegacy / { notToP &&& legacy77P } { addSpanAndMatch TId }- <st,iif> "=" { addSpan TOpAssign }-- -- Tokens related to control statements- <keyword> "goto" { toSC st >> addSpan TGoto }- <keyword> "if" / { ifP } { toSC iif >> addSpan TIf }- <st,keyword> "then" / { fortran77P } { toSC keyword >> addSpan TThen }- <keyword> "else" / {fortran77P } { addSpan TElse }- <keyword> "elseif" / {fortran77P } { toSC st >> addSpan TElsif }- <keyword> "endif" / {fortran77P } { addSpan TEndif }- <keyword> "call" { toSC st >> addSpan TCall }- <keyword> "return" { toSC st >> addSpan TReturn }- <keyword> "save" / { fortran77P } { toSC st >> addSpan TSave }- <keyword> "continue" { toSC st >> addSpan TContinue }- <keyword> "stop" { toSC st >> addSpan TStop }- <keyword> "exit" / { extended77P } { toSC st >> addSpan TExit }- <keyword> "cycle" / { legacy77P } { toSC st >> addSpan TCycle }- <keyword> "case" / { legacy77P } { toSC st >> addSpan TCase }- <keyword> "casedefault" / { legacy77P } { toSC st >> addSpan TCaseDefault }- <keyword> "selectcase" / { legacy77P } { toSC st >> addSpan TSelectCase }- <keyword> "endselect" / { legacy77P } { toSC st >> addSpan TEndSelect }- <keyword> "pause" { toSC st >> addSpan TPause }- <keyword> "dowhile" / { extended77P } { toSC st >> addSpan TDoWhile }- <keyword> "enddo" / { extended77P } { toSC st >> addSpan TEndDo }- <keyword> "do" { toSC doo >> addSpan TDo }- <doo> @integerConst { addSpanAndMatch TInt }- <doo> "while" / { extended77P } { toSC st >> addSpan TWhile }- <doo> @id { toSC st >> addSpanAndMatch TId }- <doo> @idExtended / { extended77P } { toSC st >> addSpanAndMatch TId }- <doo> @idLegacy / { legacy77P } { toSC st >> addSpanAndMatch TId }-- -- Tokens related to I/O statements- <keyword> "read" { toSC st >> addSpan TRead }- <keyword> "write" { toSC st >> addSpan TWrite }- <keyword> "rewind" { toSC st >> addSpan TRewind }- <keyword> "backspace" { toSC st >> addSpan TBackspace }- <keyword> "endfile" { toSC st >> addSpan TEndfile }- <keyword> "inquire" / { fortran77P } { toSC st >> addSpan TInquire }- <keyword> "open" / { fortran77P } { toSC st >> addSpan TOpen }- <keyword> "close" / { fortran77P } { toSC st >> addSpan TClose }- <keyword> "print" / { fortran77P } { toSC st >> addSpan TPrint }- <keyword> "type" / { legacy77P } { toSC st >> addSpan TTypePrint }-- -- Tokens related to non-executable statements-- -- Tokens related to speification statements- <keyword> "dimension" { toSC st >> addSpan TDimension }- <keyword> "common" { toSC st >> addSpan TCommon }- <keyword> "equivalence" { toSC st >> addSpan TEquivalence }- <keyword> "external" { toSC st >> addSpan TExternal }- <keyword> "intrinsic" / { fortran77P } { toSC st >> addSpan TIntrinsic }- <keyword> @datatype { typeSCChange >> addSpanAndMatch TType }- <st> @datatype / { implicitStP } { addSpanAndMatch TType }-- <keyword> "doublecomplex" / { extended77P } { typeSCChange >> addSpanAndMatch TType }- <st> "doublecomplex" / { implicitTypeExtendedP } { addSpanAndMatch TType }- <keyword> "character" / { fortran77P } { typeSCChange >> addSpanAndMatch TType }- <st> "character" / { implicitType77P } { addSpanAndMatch TType }- <keyword> "implicit" / { fortran77P } { toSC st >> addSpan TImplicit }- <st> "none" / { implicitType77P } { addSpan TNone }- <keyword> "parameter" / { fortran77P } { toSC st >> addSpan TParameter }- <keyword> "entry" / { fortran77P } { toSC st >> addSpan TEntry }- <keyword> "pointer" / { legacy77P } { toSC st >> addSpan TPointer }-- -- 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 }- <fmt> "(".*")" { toSC st >> exitFormat >> addSpanAndMatch TBlob }-- -- Tokens needed to parse integers, reals, double precision and complex- -- constants- <st,iif> @exponent / { exponentP } { addSpanAndMatch TExponent }- <st,iif> @integerConst { addSpanAndMatch TInt }- -- can be part (end) of function type declaration- <keyword> @integerConst { typeSCChange >> addSpanAndMatch TInt }- <st,iif,keyword> @bozLiteralConst / { legacy77P } { addSpanAndMatch $ \ss s -> TBozLiteral ss (parseBoz s) }-- -- String- <st,iif> \' / { fortran77P } { strAutomaton '\'' 0 }- <st,iif> \" / { legacy77P } { strAutomaton '"' 0 }-- -- Logicals- <st,iif> ".true." { addSpan (\s -> TBool s True) }- <st,iif> ".false." { addSpan (\s -> TBool s False) }-- -- Arithmetic operators- <st,iif> "+" { addSpan TOpPlus }- <st,iif> "-" { addSpan TOpMinus }- <st,iif> "**" { addSpan TOpExp }- <st,iif> "*" { addSpan TStar }- -- can be part of function type declaration- <keyword> "*" / { legacy77P } { addSpan TStar }- <st,iif> "/" { addSpan TSlash }- <st,iif> "&" / { legacy77P } { addSpan TAmpersand }-- -- Logical operators- <st,iif> ".or." { addSpan TOpOr }- <st,iif> ".and." { addSpan TOpAnd }- <st,iif> ".not." { addSpan TOpNot }- <st,iif> ".xor." / { legacy77P } { addSpan TOpXOr }- <st,iif> ".eqv." / { fortran77P } { addSpan TOpEquivalent }- <st,iif> ".neqv." / { fortran77P } { addSpan TOpNotEquivalent }-- -- Relational operators- <st,iif> "<" / { extended77P } { addSpan TOpLT }- <st,iif> "<=" / { extended77P } { addSpan TOpLE }- <st,iif> "==" / { extended77P } { addSpan TOpEQ }- <st,iif> "/=" / { extended77P } { addSpan TOpNE }- <st,iif> ">" / { extended77P } { addSpan TOpGT }- <st,iif> ">=" / { extended77P } { addSpan TOpGE }- <st,iif> ".lt." { addSpan TOpLT }- <st,iif> ".le." { addSpan TOpLE }- <st,iif> ".eq." { addSpan TOpEQ }- <st,iif> ".ne." { addSpan TOpNE }- <st,iif> ".gt." { addSpan TOpGT }- <st,iif> ".ge." { addSpan TOpGE }-- -- ID- <st,iif> @id { addSpanAndMatch TId }- <st,iif> @idExtended / { extended77P } { addSpanAndMatch TId }- <st,iif> @idLegacy / { legacy77P } { addSpanAndMatch TId }-- -- Strings- <st> @posIntegerConst "h" / { fortran66P } { lexHollerith }- <st,iif> @posIntegerConst "h" / { hollerithP &&& legacy77P } { lexHollerith }--{------------------------------------------------------------------------------------- Predicated lexer helpers-----------------------------------------------------------------------------------(&&&) :: (FortranVersion -> AlexInput -> Int -> AlexInput -> Bool)- -> (FortranVersion -> AlexInput -> Int -> AlexInput -> Bool)- -> (FortranVersion -> AlexInput -> Int -> AlexInput -> Bool)-f &&& g = \ fv ai1 i ai2 -> f fv ai1 i ai2 && g fv ai1 i ai2--formatExtendedP :: FortranVersion -> AlexInput -> Int -> AlexInput -> Bool-formatExtendedP fv _ _ ai = fv `elem` [Fortran77Extended, Fortran77Legacy] &&- case xs of- [ TFormat _, _ ] -> False- [ TLabel _ _, TFormat _ ] -> False- _ -> True- where- xs = take 2 . reverse . aiPreviousTokensInLine $ ai--implicitType77P :: FortranVersion -> AlexInput -> Int -> AlexInput -> Bool-implicitType77P fv b c d = fortran77P fv b c d && implicitStP fv b c d--implicitTypeExtendedP :: FortranVersion -> AlexInput -> Int -> AlexInput -> Bool-implicitTypeExtendedP fv b c d = extended77P fv b c d && implicitStP fv b c d--implicitStP :: FortranVersion -> AlexInput -> Int -> AlexInput -> Bool-implicitStP _ _ _ ai = checkPreviousTokensInLine f ai- where- f (TImplicit _) = True- f _ = False--extendedIdP :: FortranVersion -> AlexInput -> Int -> AlexInput -> Bool-extendedIdP fv a b ai = fv `elem` [Fortran77Extended, Fortran77Legacy] && idP fv a b ai--legacyIdP :: FortranVersion -> AlexInput -> Int -> AlexInput -> Bool-legacyIdP fv a b ai = fv == Fortran77Legacy && idP fv a b ai--idP :: FortranVersion -> AlexInput -> Int -> AlexInput -> Bool-idP fv ao i ai = not (doP fv ai) && not (ifP fv ao i ai)- && (equalFollowsP fv ai || rParFollowsP fv ai)--doP :: FortranVersion -> AlexInput -> Bool-doP fv ai = isPrefixOf "do" (reverse . lexemeMatch . aiLexeme $ ai) &&- case unParse (lexer $ f (0::Integer)) ps of- ParseOk True _ -> True- _ -> False- where- ps = ParseState- { psAlexInput = ai { aiStartCode = st}- , psVersion = fv- , psFilename = "<unknown>"- , psParanthesesCount = ParanthesesCount 0 False- , psContext = [ ConStart ] }- f 0 t =- case t of- TNewline{} -> return False- TEOF{} -> return False- TLeftPar{} -> lexer $ f 1- TComma{} -> return True- _ -> lexer $ f 0- f !n t =- case t of- TLeftPar{} -> lexer $ f (n+1)- TRightPar{} -> lexer $ f (n-1)- _ -> lexer $ f n--ifP :: FortranVersion -> AlexInput -> Int -> AlexInput -> Bool-ifP fv _ _ ai = "if" == (reverse . lexemeMatch . aiLexeme $ ai) &&- case unParse (lexer $ f) ps of- ParseOk True _ -> True- _ -> False- where- ps = ParseState- { psAlexInput = ai { aiStartCode = st}- , psVersion = fv- , psFilename = "<unknown>"- , psParanthesesCount = ParanthesesCount 0 False- , psContext = [ ConStart ] }- f t =- case t of- -- IF is always followed by (- TLeftPar{} -> return True- _ -> return False--functionP :: FortranVersion -> AlexInput -> Int -> AlexInput -> Bool-functionP fv _ _ ai = "function" == (reverse . lexemeMatch . aiLexeme $ ai) &&- case unParse (lexer $ f) ps of- ParseOk True _ -> True- _ -> False- where- ps = ParseState- { psAlexInput = ai { aiStartCode = st}- , psVersion = fv- , psFilename = "<unknown>"- , psParanthesesCount = ParanthesesCount 0 False- , psContext = [ ConStart ] }- f t =- case t of- -- a function keyword should be followed by the name and a left paren- TId{} -> lexer f- TLeftPar{} -> return True- _ -> return False--hollerithP :: FortranVersion -> AlexInput -> Int -> AlexInput -> Bool-hollerithP _ _ _ ai = isDigit (lookBack 2 ai)--notToP :: FortranVersion -> AlexInput -> Int -> AlexInput -> Bool-notToP _ _ _ ai = not $ "to" `isPrefixOf` (reverse . lexemeMatch . aiLexeme $ ai)--equalFollowsP :: FortranVersion -> AlexInput -> Bool-equalFollowsP fv ai =- case unParse (lexer $ f False (0::Integer)) ps of- ParseOk True _ -> True- _ -> False- where- ps = ParseState- { psAlexInput = ai { aiStartCode = st}- , psVersion = fv- , psFilename = "<unknown>"- , psParanthesesCount = ParanthesesCount 0 False- , psContext = [ ConStart ] }- f False 0 t =- case t of- TNewline{} -> return False- TEOF{} -> return False- TOpAssign{} -> return True- TLeftPar{} -> lexer $ f True 1- TDot{} -> lexer $ f False 0- TId{} -> lexer $ f False 0- _ -> return False- f False _ _ = return False- f True 0 t =- case t of- TOpAssign{} -> return True- TDot{} -> lexer $ f True 0- TId{} -> lexer $ f True 0- TLeftPar{} -> lexer $ f True 1- _ -> return False- f True n t =- case t of- TNewline{} -> return False- TEOF{} -> return False- TLeftPar{} -> lexer $ f True (n + 1)- TRightPar{} -> lexer $ f True (n - 1)- _ -> lexer $ f True n--rParFollowsP :: FortranVersion -> AlexInput -> Bool-rParFollowsP fv ai =- case unParse (lexer $ f) ps of- ParseOk True _ -> True- _ -> False- where- ps = ParseState- { psAlexInput = ai { aiStartCode = st}- , psVersion = fv- , psFilename = "<unknown>"- , psParanthesesCount = ParanthesesCount 0 False- , psContext = [ ConStart ] }- f t =- case t of- TRightPar{} -> return True- _ -> return False--commentP :: FortranVersion -> AlexInput -> Int -> AlexInput -> Bool-commentP _ aiOld _ aiNew = atColP 1 aiOld && _endsWithLine- where- _endsWithLine = (posColumn . aiPosition) aiNew /= 1--bangCommentP :: FortranVersion -> AlexInput -> Int -> AlexInput -> Bool-bangCommentP _ _ _ aiNew = _endsWithLine- where- _endsWithLine = (posColumn . aiPosition) aiNew /= 1--withinLabelColsP :: FortranVersion -> AlexInput -> Int -> AlexInput -> Bool-withinLabelColsP _ aiOld _ aiNew = getCol aiOld >= 1 && getCol aiNew <= 6- where- getCol = posColumn . aiPosition--atColP :: Int -> AlexInput -> Bool-atColP n ai = (posColumn . aiPosition) ai == n---- This predicate allows to distinguish identifiers and real exponent tokens--- by looking at previous token. Since exponent can only follow a "." or an--- integer token. Anything other previous token will prevent matching the input--- as an exponent token.-exponentP :: FortranVersion -> AlexInput -> Int -> AlexInput -> Bool-exponentP _ _ _ ai =- case aiPreviousTokensInLine ai of- -- real*8 d8 is not an exponent- TInt{} : TStar{} : TType{} : _ -> False- TInt{} : _ -> True- TDot{} : _ -> True- _ -> False--fortran66P :: FortranVersion -> AlexInput -> Int -> AlexInput -> Bool-fortran66P fv _ _ _ = fv == Fortran66--fortran77P :: FortranVersion -> AlexInput -> Int -> AlexInput -> Bool-fortran77P fv _ _ _ = fv == Fortran77 || fv == Fortran77Extended || fv == Fortran77Legacy--extended77P :: FortranVersion -> AlexInput -> Int -> AlexInput -> Bool-extended77P fv _ _ _ = fv == Fortran77Extended || fv == Fortran77Legacy--legacy77P :: FortranVersion -> AlexInput -> Int -> AlexInput -> Bool-legacy77P fv _ _ _ = fv == Fortran77Legacy-------------------------------------------------------------------------------------- Lexer helpers-----------------------------------------------------------------------------------addSpan :: (SrcSpan -> Token) -> LexAction (Maybe Token)-addSpan cons = do- s <- getLexemeSpan- return $ Just $ cons s--addSpanAndMatch :: (SrcSpan -> String -> Token) -> LexAction (Maybe Token)-addSpanAndMatch cons = do- s <- getLexemeSpan- m <- getMatch- return $ Just $ cons s m--getLexeme :: LexAction Lexeme-getLexeme = do- ai <- getAlex- return $ aiLexeme ai--putLexeme :: Lexeme -> LexAction ()-putLexeme lexeme = do- ai <- getAlex- putAlex $ ai { aiLexeme = lexeme }--resetLexeme :: LexAction ()-resetLexeme = putLexeme initLexeme--getMatch :: LexAction String-getMatch = do- lexeme <- getLexeme- return $ (reverse . lexemeMatch) lexeme--putMatch :: String -> LexAction ()-putMatch newMatch = do- lexeme <- getLexeme- putLexeme $ lexeme { lexemeMatch = reverse newMatch }--incWhiteSensitiveCharCount :: LexAction ()-incWhiteSensitiveCharCount = do- ai <- getAlex- let wsc = aiWhiteSensitiveCharCount ai- putAlex $ ai { aiWhiteSensitiveCharCount = wsc + 1 }--resetWhiteSensitiveCharCount :: LexAction ()-resetWhiteSensitiveCharCount = do- ai <- getAlex- putAlex $ ai { aiWhiteSensitiveCharCount = 0 }--setCaseSensitive :: LexAction ()-setCaseSensitive = do- ai <- getAlex- putAlex $ ai { aiCaseSensitive = True }--setCaseInsensitive :: LexAction ()-setCaseInsensitive = do- ai <- getAlex- putAlex $ ai { aiCaseSensitive = False }--enterFormat :: LexAction ()-enterFormat = do- ai <- getAlex- putAlex $ ai { aiInFormat = True }--exitFormat :: LexAction ()-exitFormat = do- ai <- getAlex- putAlex $ ai { aiInFormat = False }--instance Spanned Lexeme where- getSpan lexeme =- let ms = lexemeStart lexeme- me = lexemeEnd lexeme in- SrcSpan (fromJust ms) (fromJust me)- setSpan _ = error "Lexeme span cannot be set."--updatePreviousToken :: Maybe Token -> LexAction ()-updatePreviousToken maybeToken = do- ai <- getAlex- putAlex $ ai { aiPreviousToken = maybeToken }--addToPreviousTokensInLine :: Token -> LexAction ()-addToPreviousTokensInLine token = do- ai <- getAlex- putAlex $- case token of- TNewline _ -> updatePrevTokens ai [ ]- t -> updatePrevTokens ai $ t : aiPreviousTokensInLine ai- where- updatePrevTokens ai tokens = ai { aiPreviousTokensInLine = tokens }--checkPreviousTokensInLine :: (Token -> Bool) -> AlexInput -> Bool-checkPreviousTokensInLine prop ai = any prop $ aiPreviousTokensInLine ai--getLexemeSpan :: LexAction SrcSpan-getLexemeSpan = do- lexeme <- getLexeme- return $ getSpan lexeme---- Handle pragmas that begin with #-lexHash :: LexAction (Maybe Token)-lexHash = do- lexLineWithWhitespace $ \ m -> do- ai <- getAlex- case words (drop 1 m) of- -- 'line' pragma - rewrite the current line and filename- "line":lineStr:_- | Just line <- readInteger lineStr -> do- let revdropWNQ = reverse . drop 1 . dropWhile (flip notElem "'\"")- let file = revdropWNQ . revdropWNQ $ m- let lineOffs = fromIntegral line - posLine (aiPosition ai) - 1- let newP = (aiPosition ai) { posPragmaOffset = Just (lineOffs, file)- , posColumn = 1 }- putAlex $ ai { aiPosition = newP }- _ -> return ()- return Nothing---- Lex comments with whitespace included-lexComment :: LexAction (Maybe Token)-lexComment =- lexLineWithWhitespace $ \ m -> do- s <- getLexemeSpan- return . Just . TComment s $ tail m---- Get a line without losing the whitespace, then call continuation with it.-lexLineWithWhitespace :: (String -> LexAction (Maybe Token)) -> LexAction (Maybe Token)-lexLineWithWhitespace k = do- alex <- getAlex- let modifiedAlex = alex { aiWhiteSensitiveCharCount = 1 }- case alexGetByte modifiedAlex of- Just (w, newAlex)- | fromIntegral w /= ord '\n' -> putAlex newAlex >> lexLineWithWhitespace k- _ -> getMatch >>= k-------------------------------------------------------{-- Chars- +-+- | |- | |- | v- +-+ Nothing +-+-+---> |0|---------->+3|- +-> +++ +-+- | |-' | | '- | v- | +++ Nothing +-+- +---|1|----------->2|- +++ +++- | ^- +-------------+- Chars--}-strAutomaton :: Char -> Int -> LexAction (Maybe Token)-strAutomaton c 0 = do- setCaseSensitive- incWhiteSensitiveCharCount- alex <- getAlex- case alexGetByte alex of- Just (_, newAlex) -> do- putAlex newAlex- m <- getMatch- if last m == c- then strAutomaton c 1- else strAutomaton c 0- Nothing -> strAutomaton c 3-strAutomaton c 1 = do- incWhiteSensitiveCharCount- alex <- getAlex- case alexGetByte alex of- Just (_, newAlex) -> do- let m = lexemeMatch . aiLexeme $ newAlex- if head m == c- then do- putAlex newAlex- putMatch $ reverse . tail $ m- strAutomaton c 0- else strAutomaton c 2- Nothing -> strAutomaton c 2-strAutomaton _ 2 = do- s <- getLexemeSpan- m <- getMatch- resetWhiteSensitiveCharCount- setCaseInsensitive- return $ Just $ TString s $ (init . tail) m-strAutomaton _ _ = fail "Unmatched string."--lexHollerith :: LexAction (Maybe Token)-lexHollerith = do- match' <- getMatch- let len = read $ init match' -- Get n of "nH" from string- putMatch ""- ai <- getAlex- putAlex $ ai { aiWhiteSensitiveCharCount = len }- lexed <- lexN len- s <- getLexemeSpan- return $ do- hollerith <- lexed- return $ THollerith s hollerith--lexN :: Int -> LexAction (Maybe String)-lexN n = do- alex <- getAlex- match' <- getMatch- let len = length match'- if n == len- then return $ Just match'- else- case alexGetByte alex of- Just (w, _) | fromIntegral w == ord '\n' -> do- return . Just $! pad match'- Just (_, newAlex) -> do- putAlex newAlex- lexN n- Nothing -> return Nothing- where- pad s = s ++ replicate (n - length s) ' '--maybeToKeyword :: LexAction (Maybe Token)-maybeToKeyword = do- decPar- pcActual' <- pcActual . psParanthesesCount <$> get- if pcActual' == 0- then toSC keyword- else return Nothing--typeSCChange :: LexAction (Maybe Token)-typeSCChange = do- ps <- get- let hypotheticalPs = ps { psAlexInput = (psAlexInput ps) { aiStartCode = keyword } }- let isFunction = case unParse (lexer f) hypotheticalPs of { ParseOk True _ -> True; _ -> False }- if isFunction- then return Nothing- else toSC st- where- f TFunction{} = return True- -- can be part of function type declaration- f TLeftPar{} = lexer f- f TRightPar{} = lexer f- f TStar{} = lexer f- f TInt{} = lexer f- f _ = return False--toSC :: Int -> LexAction (Maybe Token)-toSC startCode = do- ai <- getAlex- if startCode == 0- then putAlex $ ai { aiStartCode = startCode, aiWhiteSensitiveCharCount = 6 }- else putAlex $ ai { aiStartCode = startCode }- return Nothing------------------------------------------------------------------------------------- Tokens-----------------------------------------------------------------------------------data Token = TLeftPar SrcSpan- | TRightPar SrcSpan- | TLeftArrayPar SrcSpan- | TRightArrayPar SrcSpan- | TComma SrcSpan- | TDot SrcSpan- | TPercent SrcSpan- | TColon SrcSpan- | TInclude SrcSpan- | TProgram SrcSpan- | TFunction SrcSpan- | TSubroutine SrcSpan- | TBlockData SrcSpan- | TStructure SrcSpan- | TRecord SrcSpan- | TUnion SrcSpan- | TMap SrcSpan- | TEndProgram SrcSpan- | TEndFunction SrcSpan- | TEndSubroutine SrcSpan- | TEndStructure SrcSpan- | TEndUnion SrcSpan- | TEndMap SrcSpan- | TEnd SrcSpan- | TAssign SrcSpan- | TOpAssign SrcSpan- | TTo SrcSpan- | TGoto SrcSpan- | TIf SrcSpan- | TThen SrcSpan- | TElse SrcSpan- | TElsif SrcSpan- | TEndif SrcSpan- | TCall SrcSpan- | TReturn SrcSpan- | TSave SrcSpan- | TContinue SrcSpan- | TStop SrcSpan- | TCycle SrcSpan- | TExit SrcSpan- | TCase SrcSpan- | TCaseDefault SrcSpan- | TSelectCase SrcSpan- | TEndSelect SrcSpan- | TPause SrcSpan- | TDo SrcSpan- | TDoWhile SrcSpan- | TWhile SrcSpan- | TEndDo SrcSpan- | TRead SrcSpan- | TWrite SrcSpan- | TRewind SrcSpan- | TBackspace SrcSpan- | TEndfile SrcSpan- | TInquire SrcSpan- | TOpen SrcSpan- | TClose SrcSpan- | TPrint SrcSpan- | TTypePrint SrcSpan- | TDimension SrcSpan- | TCommon SrcSpan- | TEquivalence SrcSpan- | TPointer SrcSpan- | TExternal SrcSpan- | TIntrinsic SrcSpan- | TType SrcSpan String- | TEntry SrcSpan- | TImplicit SrcSpan- | TNone SrcSpan- | TParameter SrcSpan- | TData SrcSpan- | TStatic SrcSpan- | TAutomatic SrcSpan- | TFormat SrcSpan- | TBlob SrcSpan String- | TInt SrcSpan String- | TBozLiteral SrcSpan Boz- | TExponent SrcSpan String- | TBool SrcSpan Bool- | TOpPlus SrcSpan- | TOpMinus SrcSpan- | TOpExp SrcSpan- | TStar SrcSpan- | TSlash SrcSpan- | TAmpersand SrcSpan- | TOpOr SrcSpan- | TOpAnd SrcSpan- | TOpXOr SrcSpan- | TOpNot SrcSpan- | TOpEquivalent SrcSpan- | TOpNotEquivalent SrcSpan- | TOpLT SrcSpan- | TOpLE SrcSpan- | TOpEQ SrcSpan- | TOpNE SrcSpan- | TOpGT SrcSpan- | TOpGE SrcSpan- | TId SrcSpan String- | TComment SrcSpan String- | TString SrcSpan String- | THollerith SrcSpan String- | TLabel SrcSpan String- | TNewline SrcSpan- | TEOF SrcSpan- deriving (Show, Eq, Ord, Data, Typeable, Generic)--instance FirstParameter Token SrcSpan-instance FirstParameter Token SrcSpan => Spanned Token where- getSpan a = getFirstParameter a- setSpan e a = setFirstParameter e a--instance Tok Token where- eofToken (TEOF _) = True- eofToken _ = False------------------------------------------------------------------------------------- AlexInput & related definitions-----------------------------------------------------------------------------------data Lexeme = Lexeme- { lexemeMatch :: String- , lexemeStart :: Maybe Position- , lexemeEnd :: Maybe Position- } deriving (Show)--initLexeme :: Lexeme-initLexeme = Lexeme- { lexemeMatch = ""- , lexemeStart = Nothing- , lexemeEnd = Nothing }--data AlexInput = AlexInput- { aiSourceBytes :: B.ByteString- , aiEndOffset :: Int- , aiPosition :: Position- , aiBytes :: [Word8]- , aiPreviousChar :: Char- , aiLexeme :: Lexeme- , aiWhiteSensitiveCharCount :: Int- , aiStartCode :: Int- , aiPreviousToken :: Maybe Token- , aiPreviousTokensInLine :: [ Token ]- , aiCaseSensitive :: Bool- , aiInFormat :: Bool- , aiFortranVersion :: FortranVersion- } deriving (Show)--instance Loc AlexInput where- getPos = aiPosition--instance LastToken AlexInput Token where- getLastToken = aiPreviousToken--type LexAction a = Parse AlexInput Token a--vanillaAlexInput :: AlexInput-vanillaAlexInput = AlexInput- { aiSourceBytes = B.empty- , aiEndOffset = 0- , aiPosition = initPosition- , aiBytes = []- , aiPreviousChar = '\n'- , aiLexeme = initLexeme- , aiWhiteSensitiveCharCount = 6- , aiStartCode = 0- , aiPreviousToken = Nothing- , aiPreviousTokensInLine = [ ]- , aiCaseSensitive = False- , aiInFormat = False- , aiFortranVersion = Fortran77- }--updateLexeme :: Maybe Char -> Position -> AlexInput -> AlexInput-updateLexeme maybeChar p ai =- let lexeme = aiLexeme ai- match = lexemeMatch lexeme- newMatch =- case maybeChar of- Just c -> c : match- Nothing -> match- start = lexemeStart lexeme- -- skipping should not start a new lexeme- newStart = if isNothing start && isJust maybeChar then Just p else start- newEnd = Just p in- ai { aiLexeme = Lexeme newMatch newStart newEnd }------------------------------------------------------------------------------------- Definitions needed for alexScanUser-----------------------------------------------------------------------------------data Move = Continuation | Char | Newline | NewlineComment | Comment--alexGetByte :: AlexInput -> Maybe (Word8, AlexInput)-alexGetByte ai- -- The process of reading individual bytes of the character- | _bytes /= [] = Just (head _bytes, ai { aiBytes = tail _bytes })- -- When all characters are already read- | posAbsoluteOffset _position == aiEndOffset ai = Nothing- -- Skip the continuation line altogether- | isContinuation ai && _isWhiteInsensitive = skip Continuation ai- -- Skip the newline before a comment- | aiFortranVersion ai == Fortran77Legacy && _isWhiteInsensitive- && isNewlineCommentsFollowedByContinuation ai = skip NewlineComment ai- -- If we are not parsing a Hollerith skip whitespace- | _curChar `elem` [ ' ', '\t' ] && _isWhiteInsensitive = skip Char ai- -- Ignore inline comments- | aiFortranVersion ai == Fortran77Legacy &&- _isWhiteInsensitive && not _inFormat && _curChar == '!' = skip Comment ai- -- Ignore comments after column 72 in fortran77- | aiFortranVersion ai == Fortran77Legacy && posColumn _position > 72 && _curChar /= '\n'- = skip Comment ai- -- Read genuine character and advance. Also covers white sensitivity.- | otherwise =- let (_b:_bs) = utf8Encode _curChar in- Just(_b, updateLexeme (Just _curChar) _position- ai {- aiPosition =- case _curChar of- '\n' -> advance Newline ai- _ -> advance Char ai,- aiBytes = _bs,- aiPreviousChar = _curChar,- aiWhiteSensitiveCharCount =- if _isWhiteInsensitive- then 0- else aiWhiteSensitiveCharCount ai - 1- })- where- _curChar = (if aiCaseSensitive ai then id else toLower) $ currentChar ai- _bytes = aiBytes ai- _position = aiPosition ai- _isWhiteInsensitive = aiWhiteSensitiveCharCount ai == 0- _inFormat = aiInFormat ai--alexInputPrevChar :: AlexInput -> Char-alexInputPrevChar ai = aiPreviousChar ai--takeNChars :: Integer -> AlexInput -> String-takeNChars n ai =- B.unpack . B.take (fromIntegral n) . B.drop (fromIntegral _dropN) $ aiSourceBytes ai- where- _dropN = posAbsoluteOffset . aiPosition $ ai--currentChar :: AlexInput -> Char-currentChar ai = B.index (aiSourceBytes ai) (fromIntegral . posAbsoluteOffset . aiPosition $ ai)--lookBack :: Int -> AlexInput -> Char-lookBack n ai = B.index (aiSourceBytes ai) (fromIntegral . subtract n . posAbsoluteOffset . aiPosition $ ai)--isContinuation :: AlexInput -> Bool-isContinuation ai =- take 6 _next7 == "\n " && not (last _next7 `elem` [' ', '0', '\n', '\r'])- where- _next7 = takeNChars 7 ai--isNewlineComment :: AlexInput -> Bool-isNewlineComment ai =- _next1 == "\n" && isCommentLine ai p- where- _next1 = takeNChars 1 ai- p = (aiPosition ai) { posAbsoluteOffset = posAbsoluteOffset (aiPosition ai) + 1 }--isNewlineCommentsFollowedByContinuation :: AlexInput -> Bool-isNewlineCommentsFollowedByContinuation ai- | isNewlineComment ai- = isNewlineCommentsFollowedByContinuation (ai { aiPosition = advance NewlineComment ai })- | isContinuation ai = True- | otherwise = False--skip :: Move -> AlexInput -> Maybe (Word8, AlexInput)-skip move ai =- let _newPosition = advance move ai in- alexGetByte $ updateLexeme Nothing _newPosition $ ai { aiPosition = _newPosition }--advance :: Move -> AlexInput -> Position-advance move ai =- case move of- Char ->- position { posAbsoluteOffset = _absl + 1, posColumn = _col + 1 }- Continuation ->- position { posAbsoluteOffset = _absl + 7, posColumn = 7, posLine = _line + 1 }- Newline ->- position { posAbsoluteOffset = _absl + 1, posColumn = 1, posLine = _line + 1 }- NewlineComment ->- skipComment ai- position { posAbsoluteOffset = _absl + 1, posColumn = 1, posLine = _line + 1 }- Comment ->- skipComment ai position- where- position = aiPosition ai- _col = posColumn position- _line = posLine position- _absl = posAbsoluteOffset position--skipComment :: AlexInput -> Position -> Position-skipComment ai p =- p { posAbsoluteOffset = posAbsoluteOffset p + length line- , posColumn = posColumn p + length line- }- where- line = takeLine p ai--skipCommentLines :: AlexInput -> Position -> Position-skipCommentLines ai p = go p p- where- go p' p''- -- eof is not a comment line- | not (null line)- , isCommentLine ai p''- = go p'' p''{ posAbsoluteOffset = posAbsoluteOffset p'' + length line + 1 -- skip the newline- , posColumn = 1, posLine = posLine p'' + 1- }- | isContinuation ai'- = advance Continuation ai'- | otherwise- -- after skipping comment lines, place cursor right at the last newline- = p2- where- line = takeLine p'' ai- line' = takeLine p' ai- p2 = p' { posAbsoluteOffset = posAbsoluteOffset p' + length line'- , posColumn = length line' + 1- }- ai' = ai { aiPosition = p2 }--isCommentLine :: AlexInput -> Position -> Bool-isCommentLine ai p- -- eof is not a comment line- | posAbsoluteOffset p == aiEndOffset ai- = False- | map toLower (take 1 line) `elem` ["c", "d", "!", "*"]- || all (`elem` " \t") line- || head (dropWhile (`elem` " \t") line) == '!'- = True- | otherwise- = False- where- line = takeLine p ai--takeLine :: Position -> AlexInput -> String-takeLine p ai =- B.unpack . B.takeWhile (/='\n') . B.drop (fromIntegral _dropN) $ aiSourceBytes ai- where- _dropN = posAbsoluteOffset p--utf8Encode :: Char -> [Word8]-utf8Encode = map fromIntegral . _go . ord- where- _go oc- | oc <= 0x7f = [oc]- | oc <= 0x7ff = [ 0xc0 + (oc `Data.Bits.shiftR` 6)- , 0x80 + oc Data.Bits..&. 0x3f- ]- | oc <= 0xffff = [ 0xe0 + (oc `Data.Bits.shiftR` 12)- , 0x80 + ((oc `Data.Bits.shiftR` 6) Data.Bits..&. 0x3f)- , 0x80 + oc Data.Bits..&. 0x3f- ]- | otherwise = [ 0xf0 + (oc `Data.Bits.shiftR` 18)- , 0x80 + ((oc `Data.Bits.shiftR` 12) Data.Bits..&. 0x3f)- , 0x80 + ((oc `Data.Bits.shiftR` 6) Data.Bits..&. 0x3f)- , 0x80 + oc Data.Bits..&. 0x3f- ]------------------------------------------------------------------------------------- Lexer definition-----------------------------------------------------------------------------------lexer :: (Token -> LexAction a) -> LexAction a-lexer cont = cont =<< lexer'--lexer' :: LexAction Token-lexer' = do- resetLexeme- alexInput <- getAlex- let startCode = aiStartCode alexInput- version <- getVersion- case alexScanUser version alexInput startCode of- AlexEOF -> return $ TEOF $ SrcSpan (getPos alexInput) (getPos alexInput)- AlexError _ -> do- parseState <- get- fail $ psFilename parseState ++ ": lexing failed. "- AlexSkip newAlex _ -> putAlex newAlex >> lexer'- AlexToken newAlex _ action -> do- putAlex newAlex- maybeToken <- action- case maybeToken of- Just token -> do- updatePreviousToken maybeToken- addToPreviousTokensInLine token- return token- Nothing -> lexer'--alexScanUser :: FortranVersion -> AlexInput -> Int -> AlexReturn (LexAction (Maybe Token))------------------------------------------------------------------------------------- Functions to help testing & output-----------------------------------------------------------------------------------initParseState :: B.ByteString -> FortranVersion -> String -> ParseState AlexInput-initParseState srcBytes fortranVersion filename =- _vanillaParseState { psAlexInput = _vanillaAlexInput }- where- _vanillaParseState = ParseState- { psAlexInput = undefined- , psVersion = fortranVersion- , psFilename = filename- , psParanthesesCount = ParanthesesCount 0 False- , psContext = [ ConStart ] }- _vanillaAlexInput = vanillaAlexInput- { aiSourceBytes = srcBytes- , aiEndOffset = fromIntegral $ B.length srcBytes- , aiFortranVersion = fortranVersion- , aiPosition = initPosition {filePath = filename} }--collectFixedTokens :: FortranVersion -> B.ByteString -> [Token]-collectFixedTokens version srcInput =- collectTokens lexer' $ initParseState srcInput version "<unknown>"--collectFixedTokensSafe :: FortranVersion -> B.ByteString -> Maybe [Token]-collectFixedTokensSafe version srcInput =- collectTokensSafe lexer' $ initParseState srcInput version "<unknown>"--}
− src/Language/Fortran/Lexer/FixedForm/Utils.hs
@@ -1,19 +0,0 @@-module Language.Fortran.Lexer.FixedForm.Utils where--import Language.Fortran.Lexer.FixedForm-import Language.Fortran.AST-import Language.Fortran.AST.RealLit-import Language.Fortran.Util.Position--makeReal :: Maybe Token -> Maybe Token -> Maybe Token -> Maybe (SrcSpan, String) -> Expression A0-makeReal i1 dot i2 expr =- let span1 = getSpan (i1, dot, i2)- span2 = case expr of- Just e -> getTransSpan span1 (fst e)- Nothing -> span1- i1Str = case i1 of { Just (TInt _ s) -> s ; _ -> "" }- dotStr = case dot of { Just (TDot _) -> "." ; _ -> "" }- i2Str = case i2 of { Just (TInt _ s) -> s ; _ -> "" }- exprStr = case expr of { Just (_, s) -> s ; _ -> "" }- litStr = i1Str ++ dotStr ++ i2Str ++ exprStr- in ExpValue () span2 $ ValReal (parseRealLit litStr) Nothing
− src/Language/Fortran/Lexer/FreeForm.x
@@ -1,1395 +0,0 @@--- -*- Mode: Haskell -*--{-{-# LANGUAGE DeriveDataTypeable #-}-{-# LANGUAGE BangPatterns #-}-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE UndecidableInstances #-}-{-# LANGUAGE DeriveGeneric #-}--module Language.Fortran.Lexer.FreeForm where--import Prelude hiding (span)-import Data.Data-import Data.Maybe (fromMaybe)-import Data.List (foldl')-import Data.Char (toLower)-import Data.Word (Word8)-import qualified Data.ByteString.Char8 as B--import Control.Monad (join)-import Control.Monad.State (get)--import GHC.Generics--import Language.Fortran.ParserMonad---import Language.Fortran.Version (required when ParserMonad stops exporting it)-import Language.Fortran.Util.Position-import Language.Fortran.Util.FirstParameter-import Language.Fortran.Parser.Utils (readInteger)-import Language.Fortran.AST.RealLit (RealLit, parseRealLit)-import Language.Fortran.AST.Boz--}--$digit = 0-9-$bit = 0-1-$octalDigit = 0-7-$hexDigit = [a-f $digit]--$letter = a-z-$alphanumeric = [$letter $digit \_]--$hash = [\#]--@label = $digit{1,5}-@name = $letter $alphanumeric*--@binary = b\'$bit+\'-@octal = o\'$octalDigit+\'-@hex = z\'$hexDigit+\'--@digitString = $digit+-@kindParam = (@digitString|@name)-@bozLiteralConst = (@binary|@octal|@hex)---- Real literals-$expLetter = [ed]-@exponent = [\-\+]? @digitString-@significand = @digitString? \. @digitString-@realLiteral = @significand ($expLetter @exponent)?- | @digitString $expLetter @exponent- -- The following complements @altRealLiteral . The reason it is- -- included in the general case is to reduce the number of- -- semantic predicates to be made while lexing.- | @digitString \. $expLetter @exponent-@altRealLiteral = @digitString \.--@characterLiteralBeg = (@kindParam \_)? (\'|\")------------------------------------------------------------------------------------- Start codes | Explanation------------------------------------------------------------------------------------ 0 | For statement starters--- scI | For statements that can come after logical IF--- scC | To be used in lexCharacter, it only appears to force Happy to--- | resolve it.--- scT | For types--- scN | For everything else----------------------------------------------------------------------------------tokens :---<0> "/*" { skipCComment }-<0,scN> "!".*$ { adjustComment $ addSpanAndMatch TComment }--<0> $hash.*$ { lexHash }--<0,scN,scT> (\n\r|\r\n|\n) { resetPar >> toSC 0 >> addSpan TNewline }-<0,scN,scI,scT> [\t\ ]+ ;--<scN> "(" { leftPar }-<scN> ")" / { ifConditionEndP } { decPar >> toSC scI >> addSpan TRightPar }-<scN> ")" { decPar >> addSpan TRightPar }-<scN> "(/" / { notDefinedOperP } { addSpan TLeftInitPar }-<scN> "/)" / { notDefinedOperP } { addSpan TRightInitPar }-<scN> "[" / { notDefinedOperP } { addSpan TLeftInitPar }-<scN> "]" / { notDefinedOperP } { addSpan TRightInitPar }-<scN> "," { comma }-<scN> ";" { resetPar >> toSC 0 >> addSpan TSemiColon }-<scN> ":" { addSpan TColon }-<scN> "::" { addSpan TDoubleColon }-<scN> "=" { addSpan TOpAssign}-<scN> "=>" { addSpan TArrow }-<scN> "%" { addSpan TPercent }--<0,scI> @name / { partOfExpOrPointerAssignmentP } { addSpanAndMatch TId }-<0> @name / { constructNameP } { addSpanAndMatch TId }---- Program units-<0> "program" { addSpan TProgram }-<0> "end"\ *"program" { addSpan TEndProgram }-<0> "function" { addSpan TFunction }-<scN> "function" / { typeSpecP } { addSpan TFunction }-<0> "end"\ *"function" { addSpan TEndFunction }-<scN> "result" / { resultP } { addSpan TResult }-<0> "pure" { toSC 0 >> addSpan TPure }-<0> "elemental" { toSC 0 >> addSpan TElemental }-<0> "recursive" { toSC 0 >> addSpan TRecursive }-<scN> "pure" / { typeSpecP } { toSC 0 >> addSpan TPure }-<scN> "elemental" / { typeSpecP } { toSC 0 >> addSpan TElemental }-<scN> "recursive" / { typeSpecP } { toSC 0 >> addSpan TRecursive }-<0> "subroutine" { addSpan TSubroutine }-<0> "end"\ *"subroutine" { addSpan TEndSubroutine }-<0> "block"\ *"data" { addSpan TBlockData }-<0> "end"\ *"block"\ *"data" { addSpan TEndBlockData }-<0> "module" { addSpan TModule }-<0> "end"\ *"module" { addSpan TEndModule }-<0> "contains" { addSpan TContains }-<0> "use" { addSpan TUse }-<scN> "only" / { useStP } { addSpan TOnly }-<0> "import" { addSpan TImport }-<0> "abstract" { addSpan TAbstract }-<0> "interface" { addSpan TInterface }-<scN> "interface" / { genericSpecP } { addSpan TInterface }-<0> "end"\ *"interface" { addSpan TEndInterface }-<0> "procedure" { addSpan TProcedure }-<0> "module"\ \ *"procedure" { addSpan TModuleProcedure }-<scN> "assignment"\ *"("\ *"="\ *")" / { genericSpecP } { addSpan TAssignment }-<scN> "operator" / { genericSpecP } { addSpan TOperator }-<0,scI> "call" { addSpan TCall }-<0,scI> "return" { addSpan TReturn }-<0> "entry" { addSpan TEntry }-<0> "include" { addSpan TInclude }---- Type def related-<0,scT> "type" { addSpan TType }-<scN> "type" / { allocateP } { addSpan TType }-<0> "end"\ *"type" { addSpan TEndType }-<scN> "class" / { followsProcedureP } { addSpan TClass }-<0> "sequence" { addSpan TSequence }-<0> "enum" { addSpan TEnum }-<0> "end"\ *"enum" { addSpan TEndEnum }-<0> "enumerator" { addSpan TEnumerator }---- Intrinsic types-<0,scT> "integer" { addSpan TInteger }-<scN> "integer" / { allocateP } { addSpan TInteger }-<0,scT> "real" { addSpan TReal }-<scN> "real" / { allocateP } { addSpan TReal }-<0,scT> "double"\ *"precision" { addSpan TDoublePrecision }-<scN> "double"\ *"precision" / { allocateP } { addSpan TDoublePrecision }-<0,scT> "logical" { addSpan TLogical }-<scN> "logical" / { allocateP } { addSpan TLogical }-<0,scT> "character" { addSpan TCharacter }-<scN> "character" / { allocateP } { addSpan TCharacter }-<0,scT> "complex" { addSpan TComplex }-<scN> "complex" / { allocateP } { addSpan TComplex }--<scN> "kind" / { selectorP } { addSpan TKind }-<scN> "len" / { selectorP } { addSpan TLen }---- Attributes-<0> "public" { addSpan TPublic }-<scN> "public" / { attributeP } { addSpan TPublic }-<0> "private" { addSpan TPrivate }-<scN> "private" / { attributeP } { addSpan TPrivate }-<0> "protected" { addSpan TProtected }-<scN> "protected" / { attributeP } { addSpan TProtected }-<0> "parameter" { addSpan TParameter }-<scN> "parameter" / { attributeP } { addSpan TParameter }-<0> "allocatable" { addSpan TAllocatable }-<scN> "allocatable" / { attributeP } { addSpan TAllocatable }-<0> "asynchronous" { addSpan TAsynchronous }-<scN> "asynchronous" / { attributeP } { addSpan TAsynchronous }-<0> "dimension" { addSpan TDimension }-<scN> "dimension" / { attributeP } { addSpan TDimension }-<0> "external" { addSpan TExternal }-<scN> "external" / { attributeP } { addSpan TExternal }-<0> "intent" { addSpan TIntent }-<scN> "intent" / { attributeP } { addSpan TIntent }-<0> "intrinsic" { addSpan TIntrinsic }-<scN> "intrinsic" / { attributeP } { addSpan TIntrinsic }-<0> "non_intrinsic" { addSpan TNonIntrinsic }-<scN> "non_intrinsic" / { attributeP } { addSpan TNonIntrinsic }-<0> "optional" { addSpan TOptional }-<scN> "optional" / { attributeP } { addSpan TOptional }-<0> "pointer" { addSpan TPointer }-<scN> "pointer" / { attributeP } { addSpan TPointer }-<0> "save" { addSpan TSave }-<scN> "save" / { attributeP } { addSpan TSave }-<0> "target" { addSpan TTarget }-<scN> "target" / { attributeP } { addSpan TTarget }-<0> "save" { addSpan TSave }-<scN> "save" / { attributeP } { addSpan TSave }-<0> "value" { addSpan TValue }-<scN> "value" / { attributeP } { addSpan TValue }-<0> "volatile" { addSpan TVolatile }-<scN> "volatile" / { attributeP } { addSpan TVolatile }---- Attribute values-<scN> "in"\ *"out" / { followsIntentP } { addSpan TInOut }-<scN> "in" / { followsIntentP } { addSpan TIn }-<scN> "out" / { followsIntentP } { addSpan TOut }---- language-binding-spec-<scN> "bind" / { bindP } { addSpan TBind }-<scN> "name" / { followsCP } { addSpan TName }-<scN> "c" / { followsBindP } { addSpan TC }---- Control flow-<0> "do" { addSpan TDo }-<scN> "do" / { followsColonP } { addSpan TDo }-<0> "end"\ *"do" { addSpan TEndDo }-<scN> "while" / { followsDoWithOptLabelP } { addSpan TWhile }-<0> "if" { addSpan TIf }-<scN> "if" / { followsColonP } { addSpan TIf }-<scI> "then" { addSpan TThen }-<0> "else" { addSpan TElse }-<0> "else"\ *"if" { addSpan TElsif }-<0> "end"\ *"if" { addSpan TEndIf }-<0> "select"\ *"case" { addSpan TSelectCase }-<scN> "select"\ *"case" / { followsColonP } { addSpan TSelectCase }-<0> "case" { addSpan TCase }-<0> "end"\ *"select" { addSpan TEndSelect }-<scN> "default" / { caseStP } { addSpan TDefault }-<0,scI> "cycle" { addSpan TCycle }-<0,scI> "exit" { addSpan TExit }-<0,scI> "go"\ *"to" { addSpan TGoto }-<0,scI> "assign" { addSpan TAssign }-<scN> "to" / { assignStP } { addSpan TTo }-<0,scI> "continue" { addSpan TContinue }-<0,scI> "stop" { addSpan TStop }-<0,scI> "pause" { addSpan TPause }-<0> "forall" { addSpan TForall }-<0> "end"\ *"forall" { addSpan TEndForall }-<0> "associate" { addSpan TAssociate }-<scN> "associate" / { followsColonP } { addSpan TAssociate }-<0> "end"\ *"associate" { addSpan TEndAssociate }----- Where construct-<0,scI> "where" { addSpan TWhere }-<scN> "where" / { labelledWhereP } { addSpan TWhere }-<0> "elsewhere" { addSpan TElsewhere }-<0> "else"\ *"where" { addSpan TElsewhere }-<0> "end"\ *"where" { addSpan TEndWhere }---- Beginning keyword-<0> "data" { addSpan TData }-<0,scI> "allocate" { addSpan TAllocate }-<scN> "stat" / { allocateP } { addSpan TStat }-<scN> "errmsg" / { allocateP } { addSpan TErrMsg }-<scN> "source" / { allocateP } { addSpan TSource }-<0,scI> "deallocate" { addSpan TDeallocate }-<0,scI> "nullify" { addSpan TNullify }-<0> "namelist" { addSpan TNamelist }-<0> "implicit" { toSC scT >> addSpan TImplicit }-<0> "equivalence" { addSpan TEquivalence }-<0> "common" { addSpan TCommon }-<0> "end" { addSpan TEnd }--<scT> "none" { addSpan TNone }---- I/O-<0,scI> "open" { addSpan TOpen }-<0,scI> "close" { addSpan TClose }-<0,scI> "read" { addSpan TRead }-<0,scI> "write" { addSpan TWrite }-<0,scI> "print" { addSpan TPrint }-<0,scI> "backspace" { addSpan TBackspace }-<0,scI> "rewind" { addSpan TRewind }-<0,scI> "inquire" { addSpan TInquire }-<0,scI> "end"\ *"file" { addSpan TEndfile }-<0> "flush" { addSpan TFlush }-<scN> "unit" / { followsFlushP } { addSpan TUnit }-<scN> "iostat" / { followsFlushP } { addSpan TIOStat }-<scN> "iomsg" / { followsFlushP } { addSpan TIOMsg }-<scN> "err" / { followsFlushP } { addSpan TErr }---- Format-<0> "format" { addSpan TFormat }-<scN> "(".*")" / { formatP } { addSpanAndMatch TBlob }---- Literals-<scN> "_" { addSpan TUnderscore }-<0> @label { toSC 0 >> addSpanAndMatch TIntegerLiteral }-<scN,scI> @digitString { addSpanAndMatch TIntegerLiteral }-<scN> @bozLiteralConst { addSpanAndMatch $ \ss s -> TBozLiteral ss (parseBoz s) }--<scN> @realLiteral { addSpanAndMatch $ \ss s -> TRealLiteral ss (parseRealLit s) }-<scN> @altRealLiteral / { notPrecedingDotP } { addSpanAndMatch $ \ss s -> TRealLiteral ss (parseRealLit s) }--<scN,scC> @characterLiteralBeg { lexCharacter }--<scN> ".true." { addSpan (\s -> TLogicalLiteral s True) }-<scN> ".false." { addSpan (\s -> TLogicalLiteral s False) }---- Operators-<scN> ("."$letter+"."|"**"|\*|\/|\+|\-) / { opP } { addSpanAndMatch TOpCustom }-<scN> "**" { addSpan TOpExp }-<scN> "+" { addSpan TOpPlus }-<scN> "-" { addSpan TOpMinus }-<scN> "*" { addSpan TStar }-<scN> "/" { slashOrDivision }-<scN> ".or." { addSpan TOpOr }-<scN> ".and." { addSpan TOpAnd }-<scN> ".not." { addSpan TOpNot }-<scN> ".eqv." { addSpan TOpEquivalent }-<scN> ".neqv." { addSpan TOpNotEquivalent }-<scN> (".eq."|"==") { addSpan TOpEQ }-<scN> (".ne."|"/=") { addSpan TOpNE }-<scN> (".lt."|"<") { addSpan TOpLT }-<scN> (".le."|"<=") { addSpan TOpLE }-<scN> (".gt."|">") { addSpan TOpGT }-<scN> (".ge."|">=") { addSpan TOpGE }-<scN> "." $letter+ "." { addSpanAndMatch TOpCustom }--<scN> @name { addSpanAndMatch TId }--{------------------------------------------------------------------------------------- Predicated lexer helpers-----------------------------------------------------------------------------------formatP :: User -> AlexInput -> Int -> AlexInput -> Bool-formatP _ _ _ ai- | Just TFormat{} <- aiPreviousToken ai = True- | otherwise = False--followsDoWithOptLabelP :: User -> AlexInput -> Int -> AlexInput -> Bool-followsDoWithOptLabelP _ _ _ ai- -- DO ...- | Just TDo {} <- aiPreviousToken ai = True-- -- DO 10 ...- | TDo{}:TIntegerLiteral{}:[] <- prevTokens = True-- | otherwise = False- where- prevTokens = reverse . aiPreviousTokensInLine $ ai--followsColonP :: User -> AlexInput -> Int -> AlexInput -> Bool-followsColonP _ _ _ ai- | Just TColon{} <- aiPreviousToken ai = True- | otherwise = False--labelledWhereP :: User -> AlexInput -> Int -> AlexInput -> Bool-labelledWhereP _ _ _ ai- | TId{}:TColon{}:[] <- prevTokens = True- | otherwise = False- where- prevTokens = reverse . aiPreviousTokensInLine $ ai--selectorP :: User -> AlexInput -> Int -> AlexInput -> Bool-selectorP user _ _ ai =- followsType && nextTokenIsOpAssign && precedesDoubleColon ai- where- nextTokenIsOpAssign = nextTokenConstr user ai == (Just . fillConstr $ TOpAssign)- followsType =- case searchBeforePar (aiPreviousTokensInLine ai) of- Just x -> isTypeSpec x- Nothing -> False- searchBeforePar [] = Nothing- searchBeforePar (x:xs)- | TLeftPar{} <- x = if null xs then Nothing else (Just $ head xs)- | otherwise = searchBeforePar xs--ifConditionEndP :: User -> AlexInput -> Int -> AlexInput -> Bool-ifConditionEndP (User _ pc) _ _ ai- | (TIf{}:_) <- prevTokens = pc == ParanthesesCount 1 False- | (TIntegerLiteral{}:TIf{}:_) <- prevTokens = pc == ParanthesesCount 1 False- | (TId{}:TColon{}:TIf{}:_) <- prevTokens = pc == ParanthesesCount 1 False- | (TElsif{}:_) <- prevTokens = pc == ParanthesesCount 1 False- | otherwise = False- where- prevTokens = reverse . aiPreviousTokensInLine $ ai--opP :: User -> AlexInput -> Int ->AlexInput -> Bool-opP _ _ _ ai- | (TLeftPar{}:TOperator{}:_) <- aiPreviousTokensInLine ai = True- | otherwise = False--partOfExpOrPointerAssignmentP :: User -> AlexInput -> Int -> AlexInput -> Bool-partOfExpOrPointerAssignmentP (User fv pc) _ _ ai =- case unParse (lexer $ f False (0::Integer)) ps of- ParseOk True _ -> True- _ -> False- where- ps = ParseState- { psAlexInput = ai { aiStartCode = StartCode scN Return }- , psVersion = fv- , psFilename = "<unknown>"- , psParanthesesCount = pc- , psContext = [ ConStart ] }- f leftParSeen parCount token- | not leftParSeen =- case token of- TNewline{} -> return False- TSemiColon{} -> return False- TEOF{} -> return False- TPercent{} -> return True- TArrow{} -> return True- TOpAssign{} -> return True- TLeftPar{} -> lexer $ f True 1- TLeftPar2{} -> lexer $ f True 1- _ -> return False- | parCount == 0 =- case token of- TOpAssign{} -> return True- TArrow{} -> return True- TPercent{} -> return True- TLeftPar{} -> lexer $ f True 1- TLeftPar2{} -> lexer $ f True 1- _ -> return False- | parCount > 0 =- case token of- TNewline{} -> return False- TSemiColon{} -> return False- TEOF{} -> return False- TLeftPar{} -> lexer $ f True (parCount + 1)- TLeftPar2{} -> lexer $ f True (parCount + 1)- TRightPar{} -> lexer $ f True (parCount - 1)- _ -> lexer $ f True parCount- | otherwise =- error "Error while executing part of expression assignment predicate."--precedesDoubleColon :: AlexInput -> Bool-precedesDoubleColon ai = not . flip seenConstr ai . fillConstr $ TDoubleColon--parenLevel :: [Token] -> Int-parenLevel = foldl' f 0- where- f n tok | fillConstr TLeftPar == toConstr tok = n + 1- | fillConstr TRightPar == toConstr tok = n - 1- | otherwise = n--allocateP :: User -> AlexInput -> Int -> AlexInput -> Bool-allocateP _ _ _ ai- | alloc:lpar:rest <- prevTokens- , toConstr alloc `elem` [fillConstr TAllocate, fillConstr TDeallocate]- , fillConstr TLeftPar == toConstr lpar- = null rest || (followsComma && parenLevel prevTokens == 1)- | otherwise = False- where- prevTokens = reverse . aiPreviousTokensInLine $ ai- followsComma- | Just TComma{} <- aiPreviousToken ai = True- | otherwise = False--attributeP :: User -> AlexInput -> Int -> AlexInput -> Bool-attributeP _ _ _ ai = followsComma && precedesDoubleColon ai && lineStartOK- where- followsComma- | Just TComma{} <- aiPreviousToken ai = True- | otherwise = False-- lineStartOK- -- matches e.g.: TYPE (FOO), ATTR- | typ:lpar:_:rpar:com:_ <- prevTokens- , toConstr typ `elem` [fillConstr TType, fillConstr TClass]- , toConstr lpar == fillConstr TLeftPar- , toConstr rpar == fillConstr TRightPar- = fillConstr TComma == toConstr com-- -- matches e.g.: TYPE FOO, ATTR- | typ:com:_ <- prevTokens- , toConstr typ == fillConstr TType- = fillConstr TComma == toConstr com-- -- matches e.g.: INTEGER (KIND=...), ATTR- -- or: PROCEDURE (...), ATTR- | tok:lpar:rest <- prevTokens- , isTypeSpec tok || fillConstr TProcedure == toConstr tok- , fillConstr TLeftPar == toConstr lpar- , (_, _:com:_) <- break ((fillConstr TRightPar ==) . toConstr) rest- = fillConstr TComma == toConstr com-- -- matches e.g.: INTEGER*NUM, ATTR- | tok:star:num:com:_ <- prevTokens- , isTypeSpec tok- , fillConstr TStar == toConstr star- , TIntegerLiteral{} <- num- = fillConstr TComma == toConstr com-- -- matches e.g.: INTEGER, ATTR- -- or: USE, ATTR- | tok:com:_ <- prevTokens- , isTypeSpec tok || fillConstr TUse == toConstr tok- = fillConstr TComma == toConstr com-- | otherwise = False-- prevTokens = reverse . aiPreviousTokensInLine $ ai--bindP :: User -> AlexInput -> Int -> AlexInput -> Bool-bindP _ _ _ ai = (followsRightPar && isFunSub) || (followsComma && isProcEnum)- where- followsComma- | Just TComma{} <- aiPreviousToken ai = True- | otherwise = False- followsRightPar- | Just TRightPar{} <- aiPreviousToken ai = True- | otherwise = False- isFunSub = flip any prevTokens $ \ token ->- fillConstr TFunction == toConstr token ||- fillConstr TSubroutine == toConstr token- isProcEnum = flip any prevTokens $ \ token ->- fillConstr TProcedure == toConstr token ||- fillConstr TEnum == toConstr token- prevTokens = reverse . aiPreviousTokensInLine $ ai--constructNameP :: User -> AlexInput -> Int -> AlexInput -> Bool-constructNameP user _ _ ai =- case nextTokenConstr user ai of- Just constr -> constr == fillConstr TColon- _ -> False--genericSpecP :: User -> AlexInput -> Int -> AlexInput -> Bool-genericSpecP _ _ _ ai = Just True == do- constr <- prevTokenConstr ai- if constr `elem` fmap fillConstr [ TAbstract, TInterface, TPublic, TPrivate, TProtected ]- then return True- else if constr `elem` fmap fillConstr [ TComma, TDoubleColon, TColon ]- then return $ seenConstr (fillConstr TPublic) ai ||- seenConstr (fillConstr TPrivate) ai ||- seenConstr (fillConstr TProtected) ai ||- seenConstr (fillConstr TOnly) ai- else Nothing--notDefinedOperP :: User -> AlexInput -> Int -> AlexInput -> Bool-notDefinedOperP _ _ _ ai- | prevToken:_ <- prevTokens- , fillConstr TOperator == toConstr prevToken = False- | prevToken:prevToken':_ <- prevTokens- , fillConstr TLeftPar == toConstr prevToken- , fillConstr TOperator == toConstr prevToken' = False- | otherwise = True- where- prevTokens = aiPreviousTokensInLine ai--typeSpecP :: User -> AlexInput -> Int -> AlexInput -> Bool-typeSpecP _ _ _ ai- | (prevToken:_) <- prevTokens- , isTypeSpec prevToken = True- | otherwise = isTypeSpecImmediatelyBefore $ reverse prevTokens- where- isTypeSpecImmediatelyBefore tokens@(_:xs)- | isTypeSpec tokens = True- | otherwise = isTypeSpecImmediatelyBefore xs- isTypeSpecImmediatelyBefore [] = False- prevTokens = aiPreviousTokensInLine ai--resultP :: User -> AlexInput -> Int -> AlexInput -> Bool-resultP _ _ _ ai =- (flip seenConstr ai . fillConstr $ TFunction) &&- prevTokenConstr ai == (Just $ fillConstr TRightPar)--notPrecedingDotP :: User -> AlexInput -> Int -> AlexInput -> Bool-notPrecedingDotP user _ _ ai = not $- nextTokenConstr user ai == (Just $ toConstr (TId undefined undefined))--followsIntentP :: User -> AlexInput -> Int -> AlexInput -> Bool-followsIntentP _ _ _ ai =- (map toConstr . take 2 . aiPreviousTokensInLine) ai ==- map fillConstr [ TLeftPar, TIntent ]--followsProcedureP :: User -> AlexInput -> Int -> AlexInput -> Bool-followsProcedureP _ _ _ ai =- (map toConstr . take 2 . aiPreviousTokensInLine) ai ==- map fillConstr [ TLeftPar, TProcedure ]--followsBindP :: User -> AlexInput -> Int -> AlexInput -> Bool-followsBindP _ _ _ ai =- (map toConstr . take 2 . aiPreviousTokensInLine) ai ==- map fillConstr [ TLeftPar, TBind ]--followsCP :: User -> AlexInput -> Int -> AlexInput -> Bool-followsCP _ _ _ ai =- (map toConstr . take 2 . aiPreviousTokensInLine) ai ==- map fillConstr [ TComma, TC ]--followsFlushP :: User -> AlexInput -> Int -> AlexInput -> Bool-followsFlushP _ _ _ ai = not (null toks) && fillConstr TFlush == toConstr (last toks)- where toks = aiPreviousTokensInLine ai--useStP :: User -> AlexInput -> Int -> AlexInput -> Bool-useStP _ _ _ ai = seenConstr (toConstr $ TUse undefined) ai--caseStP :: User -> AlexInput -> Int -> AlexInput -> Bool-caseStP _ _ _ ai = prevTokenConstr ai == (Just $ fillConstr TCase)--assignStP :: User -> AlexInput -> Int -> AlexInput -> Bool-assignStP _ _ _ ai = seenConstr (fillConstr TAssign) ai--prevTokenConstr :: AlexInput -> Maybe Constr-prevTokenConstr ai = toConstr <$> aiPreviousToken ai--nextTokenConstr :: User -> AlexInput -> Maybe Constr-nextTokenConstr (User fv pc) ai =- case unParse lexer' parseState of- ParseOk token _ -> Just $ toConstr token- _ -> Nothing- where- parseState = ParseState- { psAlexInput = ai- , psParanthesesCount = pc- , psVersion = fv- , psFilename = "<unknown>"- , psContext = [ ConStart ] }--seenConstr :: Constr -> AlexInput -> Bool-seenConstr candidateConstr ai =- candidateConstr `elem` (toConstr <$> aiPreviousTokensInLine ai)--fillConstr = toConstr . ($ undefined)------------------------------------------------------------------------------------- Lexer helpers-----------------------------------------------------------------------------------adjustComment :: LexAction (Maybe Token) -> LexAction (Maybe Token)-adjustComment action = do- mTok <- action- case mTok of- Just (TComment s (_:xs)) -> return $ Just $ TComment s xs- _ -> error "Either not a comment token or matched empty."--leftPar :: LexAction (Maybe Token)-leftPar = do- incPar- context <- topContext- if context == ConImplicit- then do- parseState <- get- case unParse f parseState of- ParseOk tokenCons _ -> do- span <- getLexemeSpan- return $ Just $ tokenCons span- ParseFailed _ -> fail "Left parantheses is not matched."- else addSpan TLeftPar- where- f :: LexAction (SrcSpan -> Token)- f = do- (ParanthesesCount pc _) <- getParanthesesCount- mPrevToken <- aiPreviousToken <$> getAlex- case mPrevToken of- Just TRightPar{} | pc == 0 -> do- _ <- getLexemeSpan- curToken <- lexer'- case curToken of- TComma{} -> return TLeftPar2- TNewline{} -> return TLeftPar2- TSemiColon{} -> return TLeftPar2- TEOF{} -> return TLeftPar2- _ -> return TLeftPar- _ -> lexer' >> f--comma :: LexAction (Maybe Token)-comma = do- context <- topContext- case context of- ConImplicit -> do- mToken <- aiPreviousToken <$> getAlex- case mToken of- Just TRightPar{} -> toSC scT >> addSpan TComma- _ -> addSpan TComma- ConNamelist -> secondCommaIfSlashFollows- ConCommon -> secondCommaIfSlashFollows- _ -> addSpan TComma- where- secondCommaIfSlashFollows = do- parseState <- get- case unParse lexer' parseState of- ParseOk TOpDivision{} _ -> addSpan TComma2- ParseFailed _ -> fail "Expecting variable name or slash."- _ -> addSpan TComma--slashOrDivision :: LexAction (Maybe Token)-slashOrDivision = do- context <- topContext- case context of- ConData -> addSpan TSlash- _ -> addSpan TOpDivision--addSpan :: (SrcSpan -> Token) -> LexAction (Maybe Token)-addSpan cons = do- s <- getLexemeSpan- return $ Just $ cons s--addSpanAndMatch :: (SrcSpan -> String -> Token) -> LexAction (Maybe Token)-addSpanAndMatch cons = do- s <- getLexemeSpan- m <- getMatch- return $ Just $ cons s m--getLexeme :: LexAction Lexeme-getLexeme = do- ai <- getAlex- return $ aiLexeme ai--putLexeme :: Lexeme -> LexAction ()-putLexeme lexeme = do- ai <- getAlex- putAlex $ ai { aiLexeme = lexeme }--resetLexeme :: LexAction ()-resetLexeme = putLexeme initLexeme--getMatch :: LexAction String-getMatch = do- lexeme <- getLexeme- return $ (reverse . lexemeMatch) lexeme--putMatch :: String -> LexAction ()-putMatch newMatch = do- lexeme <- getLexeme- putLexeme $ lexeme { lexemeMatch = reverse newMatch }--instance Spanned Lexeme where- getSpan lexeme = SrcSpan (lexemeStart lexeme) (lexemeEnd lexeme)- setSpan _ = error "Lexeme span cannot be set."--updatePreviousToken :: Maybe Token -> LexAction ()-updatePreviousToken maybeToken = do- ai <- getAlex- putAlex $ ai { aiPreviousToken = maybeToken }--addToPreviousTokensInLine :: Token -> LexAction ()-addToPreviousTokensInLine token = do- ai <- getAlex- putAlex $- case token of- TNewline _ -> updatePrevTokens ai [ ]- TSemiColon _ -> updatePrevTokens ai [ ]- t -> updatePrevTokens ai $ t : aiPreviousTokensInLine ai- where- updatePrevTokens ai tokens = ai { aiPreviousTokensInLine = tokens }--checkPreviousTokensInLine :: (Token -> Bool) -> AlexInput -> Bool-checkPreviousTokensInLine prop ai = any prop $ aiPreviousTokensInLine ai--getLexemeSpan :: LexAction SrcSpan-getLexemeSpan = do- lexeme <- getLexeme- return $ getSpan lexeme---- Automata for character literal parsing is given below. Wherever it says '--- you can replace ", whichever is used depends on what the first matched--- character is and they are dual in their nature.------ else--- +-+--- | v--- +-+ Nothing +-+--- +---> |0|---------->|3|--- +-> +-+ +-+--- | |--- ' | | '--- | v--- | +-+ Nothing +-+--- +---|1|---------->|2|--- +-+ +-+--- | ^--- +-------------+--- else------ For more information please refer to Fortran 90 standard's section related--- to character constants.-lexCharacter :: LexAction (Maybe Token)-lexCharacter = do- alex <- getAlex- putAlex $ alex { aiStartCode = StartCode scC Stable }- match <- getMatch- let boundaryMarker = last match- _lexChar (0::Integer) boundaryMarker- where- _lexChar 0 bm = do- alex <- getAlex- case alexGetByte alex of- Just (_, newAlex) -> do- putAlex newAlex- m <- getMatch- if last m == bm- then _lexChar 1 bm- else _lexChar 0 bm- Nothing -> fail "Unmatched character literal."- _lexChar 1 bm = do- alex <- getAlex- case alexGetByte alex of- Just (_, newAlex) -> do- let m = lexemeMatch . aiLexeme $ newAlex- if head m == bm- then do- putAlex newAlex- putMatch . reverse . tail $ m- _lexChar 0 bm- else _lexChar 2 bm- Nothing -> _lexChar 2 bm- _lexChar 2 _ = do- alex <- getAlex- putAlex $ alex { aiStartCode = StartCode scN Return }- match <- getMatch- putMatch . init . tail $ match- addSpanAndMatch TString- _lexChar _ _ = do fail "unhandled lexCharacter"--toSC :: Int -> LexAction ()-toSC startCode = do- alex <- getAlex- putAlex $ alex { aiStartCode = StartCode startCode Return }--stabiliseStartCode :: LexAction ()-stabiliseStartCode = do- alex <- getAlex- let sc = aiStartCode alex- putAlex $ alex { aiStartCode = sc { scStatus = Stable } }--normaliseStartCode :: LexAction ()-normaliseStartCode = do- alex <- getAlex- let startCode = aiStartCode alex- case scStatus startCode of- Return -> putAlex $ alex { aiStartCode = StartCode scN Stable }- Stable -> return ()------------------------------------------------------------------------------------- AlexInput & related definitions-----------------------------------------------------------------------------------invalidPosition :: Position-invalidPosition = Position 0 0 0 "" Nothing--{-# INLINE isValidPosition #-}-isValidPosition :: Position -> Bool-isValidPosition pos = posLine pos > 0--data Lexeme = Lexeme- { lexemeMatch :: !String- , lexemeStart :: {-# UNPACK #-} !Position- , lexemeEnd :: {-# UNPACK #-} !Position- , lexemeIsCmt :: !Bool- } deriving (Show)--initLexeme :: Lexeme-initLexeme = Lexeme- { lexemeMatch = ""- , lexemeStart = invalidPosition- , lexemeEnd = invalidPosition- , lexemeIsCmt = False }--data StartCodeStatus = Return | Stable deriving (Show)--data StartCode = StartCode- { scActual :: {-# UNPACK #-} !Int- , scStatus :: !StartCodeStatus }- deriving (Show)--data AlexInput = AlexInput- { aiSourceBytes :: !B.ByteString- , aiPosition :: {-# UNPACK #-} !Position- , aiEndOffset :: {-# UNPACK #-} !Int- , aiPreviousChar :: {-# UNPACK #-} !Char- , aiLexeme :: {-# UNPACK #-} !Lexeme- , aiStartCode :: {-# UNPACK #-} !StartCode- , aiPreviousToken :: !(Maybe Token)- , aiPreviousTokensInLine :: !([ Token ])- } deriving (Show)--instance Loc AlexInput where- getPos = aiPosition--instance LastToken AlexInput Token where- getLastToken = aiPreviousToken--type LexAction a = Parse AlexInput Token a--vanillaAlexInput :: AlexInput-vanillaAlexInput = AlexInput- { aiSourceBytes = B.empty- , aiPosition = initPosition- , aiEndOffset = 0- , aiPreviousChar = '\n'- , aiLexeme = initLexeme- , aiStartCode = StartCode 0 Return- , aiPreviousToken = Nothing- , aiPreviousTokensInLine = [ ] }--updateLexeme :: Char -> Position -> AlexInput -> AlexInput-updateLexeme !char !p !ai = ai { aiLexeme = Lexeme (char:match) start' p isCmt' }- where- Lexeme match start _ isCmt = aiLexeme ai- start' = if isValidPosition start then start else p- isCmt' = isCmt || (null match && char == '!')---- Fortran version and parantheses count to be used by alexScanUser-data User = User FortranVersion ParanthesesCount------------------------------------------------------------------------------------- Definitions needed for alexScanUser-----------------------------------------------------------------------------------data Move = Continuation | Char | Newline--alexGetByte :: AlexInput -> Maybe (Word8, AlexInput)-alexGetByte !ai- -- When all characters are already read- | posAbsoluteOffset _position == aiEndOffset ai = Nothing- -- Skip the continuation line altogether- | isContinuation ai = alexGetByte . skipContinuation $ ai- -- Read genuine character and advance. Also covers white sensitivity.- | otherwise =- Just ( fromIntegral . fromEnum $ _curChar- , updateLexeme _curChar _position- ai- { aiPosition =- case _curChar of- '\n' -> advance Newline _position- _ -> advance Char _position- , aiPreviousChar = _curChar })- where- _curChar = currentChar ai- _position = aiPosition ai--alexInputPrevChar :: AlexInput -> Char-alexInputPrevChar ai = aiPreviousChar ai--currentChar :: AlexInput -> Char-currentChar !ai- -- case sensitivity matters only in character literals- | sCode == scC = _currentChar- | 'A' <= _currentChar &&- _currentChar <= 'Z' = {-# SCC toLower_currentChar #-} toLower _currentChar- | otherwise = _currentChar- where- sCode = scActual (aiStartCode ai)- -- _currentChar = w2c (BU.unsafeIndex srcBytes i)- _currentChar = B.index srcBytes absOff- srcBytes = aiSourceBytes ai- absOff = posAbsoluteOffset pos- pos = aiPosition ai--advanceWithoutContinuation :: AlexInput -> Maybe AlexInput-advanceWithoutContinuation !ai- -- When all characters are already read- | posAbsoluteOffset _position == aiEndOffset ai =- Nothing- -- Read genuine character and advance. Also covers white sensitivity.- | otherwise =- Just $! ai { aiPosition =- case _curChar of- '\n' -> advance Newline _position- _ -> advance Char _position- , aiPreviousChar = _curChar }- where- _curChar = currentChar ai- _position = aiPosition ai--isContinuation :: AlexInput -> Bool-isContinuation !ai =- -- No continuation while lexing a character literal.- (scActual . aiStartCode) ai /= scC- -- No continuation while lexing a comment.- && (null match || not (lexemeIsCmt lexeme))- && _isContinuation ai (0::Integer)- where- match = lexemeMatch lexeme- lexeme = aiLexeme $ ai- _isContinuation !ai' 0 =- if currentChar ai' == '&'- then _advance ai'- else False- _isContinuation !ai' 1 =- case currentChar ai' of- ' ' -> _advance ai'- '\t' -> _advance ai'- '\r' -> _advance ai'- '!' -> True- '\n' -> True- _ -> False- _isContinuation _ _ = False- _advance :: AlexInput -> Bool- _advance !ai' =- case advanceWithoutContinuation ai' of- Just ai'' -> _isContinuation ai'' (1::Integer)- Nothing -> False---- Here's the skip continuation automaton:------ white white,\n--- +-+ +-+--- | v | v +---+--- +-+ & +-+ \n +-+ & |---|--- +-->|0|------>|1|------->|3|------->||4||--- +-+ +-+ +-+----+ |---|--- | ^ | +---+--- |! | |--- v | |else--- +->+-+ | v--- else| |2|---------+ +---+--- +--+-+ |---|--- ||5||--- |---|--- +---+------ For more information refer to Fortran 90 standard.--- This version is more permissive than the specification--- as it allows empty lines to be used between continuations.-skipContinuation :: AlexInput -> AlexInput-skipContinuation ai' = _skipCont ai' (0::Integer)- where- _skipCont ai 0 =- if currentChar ai == '&'- then _advance ai 1- else error "This case is excluded by isContinuation."- _skipCont ai 1 =- let _curChar = currentChar ai in- if _curChar `elem` [' ', '\t', '\r']- then _advance ai 1- else if _curChar == '!'- then _advance ai 2- else if _curChar == '\n'- then _advance ai 3- else- error $- join [ "Did not expect non-blank/non-comment character after "- , "continuation symbol (&)." ]- _skipCont ai 2 =- if currentChar ai == '\n'- then _advance ai 3- else _advance ai 2- _skipCont ai 3 =- let _curChar = currentChar ai in- if _curChar `elem` [' ', '\t', '\r', '\n']- then _advance ai 3- else if _curChar == '!'- then _advance ai 2- else if _curChar == '&'- -- This state accepts as if there were no spaces between the broken- -- line and whatever comes after second &. This is implicitly state (4)- then fromMaybe (error "File has ended prematurely during a continuation.")- (advanceWithoutContinuation ai)- -- This state accepts but the broken line delimits the previous token.- -- This is implicitly state (5). To achieve this, it returns the- -- previous ai, which either has whitespace or newline, so it will- -- nicely delimit.- else ai- _skipCont _ _ = error "unhandled _skipCont in skipContinuation"- _advance ai state =- case advanceWithoutContinuation ai of- Just ai'' -> _skipCont ai'' state- Nothing -> error "File has ended prematurely during a continuation."---- skip a C comment (read until first "*/")-skipCComment :: LexAction (Maybe Token)-skipCComment = do- let loop (Just ai) 0 | currentChar ai == '*' = loop (advanceWithoutContinuation ai) 1- | otherwise = loop (advanceWithoutContinuation ai) 0- loop (Just ai) 1 | currentChar ai == '/' = ai `fromMaybe` advanceWithoutContinuation ai- | otherwise = loop (advanceWithoutContinuation ai) 0- loop _ _ = error "File has ended prematurely during a C comment."- ai <- getAlex- putAlex $ loop (Just ai) (0 :: Int)- return Nothing--advance :: Move -> Position -> Position-advance move position =- case move of- Newline ->- position- { posAbsoluteOffset = _absl + 1 , posColumn = 1 , posLine = _line + 1 }- Char ->- position { posAbsoluteOffset = _absl + 1 , posColumn = _col + 1 }--- for now just return the original position- _ -> position { posAbsoluteOffset = _absl, posColumn = _col }- where- _col = posColumn position- _line = posLine position- _absl = posAbsoluteOffset position---- Handle pragmas that begin with #-lexHash :: LexAction (Maybe Token)-lexHash = do- ai <- getAlex- m <- getMatch- case words (drop 1 m) of- -- 'line' pragma - rewrite the current line and filename- "line":lineStr:_- | Just line <- readInteger lineStr -> do- let revdropWNQ = reverse . drop 1 . dropWhile (flip notElem "'\"")- let file = revdropWNQ . revdropWNQ $ m- let lineOffs = fromIntegral line - posLine (aiPosition ai) - 1- let newP = (aiPosition ai) { posPragmaOffset = Just (lineOffs, file)- , posColumn = 1 }- putAlex $ ai { aiPosition = newP }- _ -> return ()- return Nothing------------------------------------------------------------------------------------- Lexer definition-----------------------------------------------------------------------------------lexer :: (Token -> LexAction a) -> LexAction a-lexer cont = cont =<< lexer'--lexer' :: LexAction Token-lexer' = do- resetLexeme- alex <- getAlex- let startCode = scActual . aiStartCode $ alex- normaliseStartCode- newAlex' <- getAlex- version <- getVersion- paranthesesCount <- getParanthesesCount- let user = User version paranthesesCount- case alexScanUser user newAlex' startCode of- AlexEOF -> return $ TEOF $ SrcSpan (getPos alex) (getPos alex)- AlexError _ -> do- parseState <- get- fail $ psFilename parseState ++ ": lexing failed. "-#ifdef DEBUG- ++ '\n' : show newAlex ++ "\n"-#endif- AlexSkip newAlex _ -> do- putAlex $ newAlex { aiStartCode = StartCode startCode Return }- lexer'- AlexToken newAlex _ action -> do- putAlex newAlex- maybeToken <- action- case maybeToken of- Just token -> do- updatePreviousToken maybeToken- addToPreviousTokensInLine token- return token- Nothing -> lexer'--alexScanUser :: User -> AlexInput -> Int -> AlexReturn (LexAction (Maybe Token))------------------------------------------------------------------------------------- Tokens-----------------------------------------------------------------------------------data Token =- TId SrcSpan String- | TComment SrcSpan String- | TString SrcSpan String- | TIntegerLiteral SrcSpan String- | TRealLiteral SrcSpan RealLit- | TBozLiteral SrcSpan Boz- | TComma SrcSpan- | TComma2 SrcSpan- | TSemiColon SrcSpan- | TColon SrcSpan- | TDoubleColon SrcSpan- | TOpAssign SrcSpan- | TArrow SrcSpan- | TPercent SrcSpan- | TLeftPar SrcSpan- | TLeftPar2 SrcSpan- | TRightPar SrcSpan- | TLeftInitPar SrcSpan- | TRightInitPar SrcSpan- -- Mainly operators- | TOpCustom SrcSpan String- | TOpExp SrcSpan- | TOpPlus SrcSpan- | TOpMinus SrcSpan- | TStar SrcSpan- | TOpDivision SrcSpan- | TSlash SrcSpan- | TOpOr SrcSpan- | TOpAnd SrcSpan- | TOpNot SrcSpan- | TOpEquivalent SrcSpan- | TOpNotEquivalent SrcSpan- | TOpLT SrcSpan- | TOpLE SrcSpan- | TOpEQ SrcSpan- | TOpNE SrcSpan- | TOpGT SrcSpan- | TOpGE SrcSpan- | TLogicalLiteral SrcSpan Bool- | TUnderscore SrcSpan- -- Keywords- -- Program unit related- | TProgram SrcSpan- | TEndProgram SrcSpan- | TFunction SrcSpan- | TEndFunction SrcSpan- | TResult SrcSpan- | TPure SrcSpan- | TElemental SrcSpan- | TRecursive SrcSpan- | TSubroutine SrcSpan- | TEndSubroutine SrcSpan- | TBlockData SrcSpan- | TEndBlockData SrcSpan- | TModule SrcSpan- | TEndModule SrcSpan- | TContains SrcSpan- | TUse SrcSpan- | TOnly SrcSpan- | TImport SrcSpan- | TAbstract SrcSpan- | TInterface SrcSpan- | TEndInterface SrcSpan- | TProcedure SrcSpan- | TModuleProcedure SrcSpan- | TAssignment SrcSpan- | TOperator SrcSpan- | TCall SrcSpan- | TReturn SrcSpan- | TEntry SrcSpan- | TInclude SrcSpan- -- language-binding-spec- | TBind SrcSpan- | TC SrcSpan- | TName SrcSpan- -- Attributes- | TAllocatable SrcSpan- | TAsynchronous SrcSpan- | TDimension SrcSpan- | TExternal SrcSpan- | TIntent SrcSpan- | TIntrinsic SrcSpan- | TNonIntrinsic SrcSpan- | TOptional SrcSpan- | TParameter SrcSpan- | TPointer SrcSpan- | TPrivate SrcSpan- | TPublic SrcSpan- | TProtected SrcSpan- | TSave SrcSpan- | TTarget SrcSpan- | TValue SrcSpan- | TVolatile SrcSpan- -- Attribute values- | TIn SrcSpan- | TOut SrcSpan- | TInOut SrcSpan- -- Beginning keyword- | TData SrcSpan- | TNamelist SrcSpan- | TImplicit SrcSpan- | TEquivalence SrcSpan- | TCommon SrcSpan- | TFormat SrcSpan- | TBlob SrcSpan String- | TAllocate SrcSpan- | TStat SrcSpan- | TErrMsg SrcSpan- | TSource SrcSpan- | TDeallocate SrcSpan- | TNullify SrcSpan- -- Misc- | TNone SrcSpan- -- Control flow- | TGoto SrcSpan- | TAssign SrcSpan- | TTo SrcSpan- | TContinue SrcSpan- | TStop SrcSpan- | TPause SrcSpan- | TDo SrcSpan- | TEndDo SrcSpan- | TWhile SrcSpan- | TIf SrcSpan- | TThen SrcSpan- | TElse SrcSpan- | TElsif SrcSpan- | TEndIf SrcSpan- | TCase SrcSpan- | TSelectCase SrcSpan- | TEndSelect SrcSpan- | TDefault SrcSpan- | TCycle SrcSpan- | TExit SrcSpan- | TForall SrcSpan- | TEndForall SrcSpan- | TAssociate SrcSpan- | TEndAssociate SrcSpan- -- Where construct- | TWhere SrcSpan- | TElsewhere SrcSpan- | TEndWhere SrcSpan- -- Type related- | TType SrcSpan- | TEndType SrcSpan- | TSequence SrcSpan- | TClass SrcSpan- | TEnum SrcSpan- | TEnumerator SrcSpan- | TEndEnum SrcSpan- -- Selector- | TKind SrcSpan- | TLen SrcSpan- -- Intrinsic types- | TInteger SrcSpan- | TReal SrcSpan- | TDoublePrecision SrcSpan- | TLogical SrcSpan- | TCharacter SrcSpan- | TComplex SrcSpan- -- I/O- | TOpen SrcSpan- | TClose SrcSpan- | TRead SrcSpan- | TWrite SrcSpan- | TPrint SrcSpan- | TBackspace SrcSpan- | TRewind SrcSpan- | TInquire SrcSpan- | TEndfile SrcSpan- -- Etc.- | TEnd SrcSpan- | TNewline SrcSpan- | TEOF SrcSpan- | TFlush SrcSpan- | TUnit SrcSpan- | TIOStat SrcSpan- | TIOMsg SrcSpan- | TErr SrcSpan- deriving (Eq, Show, Data, Typeable, Generic)--instance FirstParameter Token SrcSpan-instance FirstParameter Token SrcSpan => Spanned Token where- getSpan = getFirstParameter- setSpan = setFirstParameter--instance Tok Token where- eofToken TEOF{} = True- eofToken _ = False--class SpecifiesType a where- isTypeSpec :: a -> Bool--instance SpecifiesType Token where- isTypeSpec TInteger{} = True- isTypeSpec TReal{} = True- isTypeSpec TDoublePrecision{} = True- isTypeSpec TLogical{} = True- isTypeSpec TCharacter{} = True- isTypeSpec TComplex{} = True- isTypeSpec _ = False--instance SpecifiesType [ Token ] where- isTypeSpec tokens- | [ TType{}, TLeftPar{}, _, TRightPar{} ] <- tokens = True- -- This is an approximation but should hold for almost all legal programs.- | (typeToken:TLeftPar{}:rest) <- tokens =- isTypeSpec typeToken &&- case last rest of- TRightPar{} -> True- _ -> False- | (TCharacter{}:TStar{}:rest) <- tokens =- case rest of- [ TIntegerLiteral{} ] -> True- (TLeftPar{}:rest') | TRightPar{} <- last rest' -> True- _ -> False- | otherwise = False------------------------------------------------------------------------------------- Functions to help testing & output-----------------------------------------------------------------------------------initParseState :: B.ByteString -> FortranVersion -> String -> ParseState AlexInput-initParseState srcBytes fortranVersion filename =- _vanillaParseState { psAlexInput = _vanillaAlexInput }- where- _vanillaParseState = ParseState- { psAlexInput = undefined- , psVersion = fortranVersion- , psFilename = filename- , psParanthesesCount = ParanthesesCount 0 False- , psContext = [ ConStart ] }- _vanillaAlexInput = vanillaAlexInput- { aiSourceBytes = srcBytes- , aiEndOffset = B.length srcBytes- , aiPosition = initPosition {filePath = filename} }--collectFreeTokens :: FortranVersion -> B.ByteString -> [Token]-collectFreeTokens version srcInput =- collectTokens lexer' $ initParseState srcInput version "<unknown>"--}
+ src/Language/Fortran/Parser.hs view
@@ -0,0 +1,338 @@+{-| 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.+-}++{-# LANGUAGE ScopedTypeVariables #-}++module Language.Fortran.Parser+ (+ -- * Main parsers (ProgramFile, with transformation)+ byVer, byVerWithMods+ , f66, f77, f77e, f77l, f90, f95, f2003++ -- * Main parsers without post-parse transformation+ , f66NoTransform, f77NoTransform, f77eNoTransform, f77lNoTransform+ , f90NoTransform, f95NoTransform, f2003NoTransform++ -- * Other parsers+ , f90Expr++ -- * Various combinators+ , transformAs, defaultTransformation+ , Parser, StateInit, ParserMaker, makeParser, makeParserFixed, makeParserFree+ , initParseStateFixed, initParseStateFree+ , initParseStateFixedExpr, initParseStateFreeExpr+ , parseUnsafe+ , collectTokensSafe, collectTokens++ -- * F77 with inlined includes+ -- $f77includes+ , f77lIncludes+ ) 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 )+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++--------------------------------------------------------------------------------++byVer :: FortranVersion -> Parser (ProgramFile A0)+byVer = \case+ Fortran66 -> f66+ Fortran77 -> f77+ Fortran77Extended -> f77e+ Fortran77Legacy -> f77l+ Fortran90 -> f90+ Fortran95 -> f95+ Fortran2003 -> f2003+ v -> error $ "Language.Fortran.Parser.byVer: "+ <> "no parser available for requested version: "+ <> show v++byVerWithMods :: ModFiles -> FortranVersion -> Parser (ProgramFile A0)+byVerWithMods mods = \case+ Fortran66 -> f66Mods mods+ Fortran77 -> f77Mods mods+ Fortran77Extended -> f77eMods mods+ Fortran77Legacy -> f77lMods mods+ Fortran90 -> f90Mods mods+ Fortran95 -> f95Mods mods+ Fortran2003 -> f2003Mods mods+ v -> error $ "Language.Fortran.Parser.byVerWithMods: no parser available for requested version: " <> show v++f66, f77, f77e, f77l, f90, f95, f2003 :: Parser (ProgramFile A0)+f66 = f66Mods []+f77 = f77Mods []+f77e = f77eMods []+f77l = f77lMods []+f90 = f90Mods []+f95 = f95Mods []+f2003 = f2003Mods []++f66Mods, f77Mods, f77eMods, f77lMods, f90Mods, f95Mods, f2003Mods+ :: ModFiles -> Parser (ProgramFile A0)+f66Mods = transformAs Fortran66 f66NoTransform+f77Mods = transformAs Fortran77 f77NoTransform+f77eMods = transformAs Fortran77Extended f77eNoTransform+f77lMods = transformAs Fortran77Legacy f77lNoTransform+f90Mods = transformAs Fortran90 f90NoTransform+f95Mods = transformAs Fortran95 f95NoTransform+f2003Mods = transformAs Fortran2003 f2003NoTransform++f66NoTransform, f77NoTransform, f77eNoTransform, f77lNoTransform,+ f90NoTransform, f95NoTransform, f2003NoTransform+ :: Parser (ProgramFile A0)+f66NoTransform = makeParserFixed F66.programParser Fortran66+f77NoTransform = makeParserFixed F77.programParser Fortran77+f77eNoTransform = makeParserFixed F77.programParser Fortran77Extended+f77lNoTransform = makeParserFixed F77.programParser Fortran77Legacy+f90NoTransform = makeParserFree F90.programParser Fortran90+f95NoTransform = makeParserFree F95.programParser Fortran95+f2003NoTransform = makeParserFree F2003.programParser Fortran2003++f90Expr :: Parser (Expression A0)+f90Expr = makeParser initParseStateFreeExpr F90.expressionParser Fortran90++--------------------------------------------------------------------------------++transformAs+ :: Data a+ => FortranVersion -> Parser (ProgramFile a) -> ModFiles+ -> Parser (ProgramFile a)+transformAs fv p mods fn bs = do+ pf <- p fn bs+ let pf' = pfSetFilename fn pf+ return $ transform pf'+ where transform = runTransform (combinedTypeEnv mods)+ (combinedModuleMap mods)+ (defaultTransformation 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 = \case+ Fortran66 -> sequence_ [ Trans.groupLabeledDo+ , Trans.disambiguateIntrinsic+ , Trans.disambiguateFunction ]+ Fortran77 -> defaultTransformation Fortran66+ Fortran77Legacy -> sequence_ [ Trans.groupLabeledDo+ , Trans.groupDo+ , Trans.disambiguateIntrinsic+ , Trans.disambiguateFunction ]+ _ -> defaultTransformation 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 fInitState p fv fn = fromParseResult . runParse p . fInitState fn fv++makeParserFixed :: ParserMaker Fixed.AlexInput Fixed.Token a+makeParserFixed = makeParser initParseStateFixed++makeParserFree :: ParserMaker Free.AlexInput Free.Token a+makeParserFree = makeParser initParseStateFree++initParseStateFixed :: StateInit Fixed.AlexInput+initParseStateFixed fn fv bs = initParseState fn fv ai+ where ai = Fixed.vanillaAlexInput fn fv bs++initParseStateFree :: StateInit Free.AlexInput+initParseStateFree fn fv bs = initParseState fn fv ai+ where ai = Free.vanillaAlexInput fn 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 fn fv bs = st+ { psAlexInput = ai { Free.aiStartCode = Free.StartCode Free.scN Free.Return } }+ where+ ai = Free.vanillaAlexInput fn bs+ st = initParseStateFree fn fv 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 fn fv bs = st+ { psAlexInput = ai { Fixed.aiStartCode = 6+ , Fixed.aiWhiteSensitiveCharCount = 0 } }+ where+ ai = Fixed.vanillaAlexInput fn fv bs+ st = initParseStateFixed fn fv 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 p bs =+ case p "<unknown>" bs of+ Left err -> throwIOError $ "Language.Fortran.Parser.parseUnsafe: "+ <> "parse error: " <> show err+ Right a -> a++-- | Helper for preparing initial parser state for the different lexers.+initParseState :: FilePath -> FortranVersion -> ai -> ParseState ai+initParseState fn fv ai = ParseState+ { psAlexInput = ai+ , psVersion = fv+ , psFilename = fn+ , psParanthesesCount = ParanthesesCount 0 False+ , psContext = [ 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.+-}++f77lIncludes+ :: [FilePath] -> ModFiles -> String -> B.ByteString+ -> IO (ProgramFile A0)+f77lIncludes incs mods fn bs = do+ -- includes files have to end with 2 newlines (unknown why, parser related)+ case f77lNoTransform fn (B.snoc bs '\n') of+ Left e -> liftIO $ throwIO e+ Right pf -> do+ let pf' = pfSetFilename fn pf+ pf'' <- evalStateT (descendBiM (f77lIncludesInline incs []) pf') Map.empty+ let pf''' = runTransform (combinedTypeEnv mods)+ (combinedModuleMap mods)+ (defaultTransformation Fortran77Legacy)+ pf''+ return pf'''++f77lIncludesInner :: Parser [Block A0]+f77lIncludesInner = makeParserFixed F77.includesParser Fortran77Legacy++f77lIncludesInline+ :: [FilePath] -> [FilePath] -> Statement A0+ -> StateT (Map String [Block A0]) IO (Statement A0)+f77lIncludesInline dirs seen st = case st of+ StInclude a s e@(ExpValue _ _ (ValString path)) Nothing -> do+ if notElem path seen then do+ incMap <- get+ case Map.lookup path incMap of+ Just blocks' -> pure $ StInclude a s e (Just blocks')+ Nothing -> do+ (fullPath, inc) <- liftIO $ readInDirs dirs path+ case f77lIncludesInner fullPath inc of+ Right blocks -> do+ blocks' <- descendBiM (f77lIncludesInline dirs (path:seen)) blocks+ modify (Map.insert path blocks')+ return $ StInclude a s e (Just blocks')+ Left err -> liftIO $ throwIO err+ else return st+ _ -> return st++readInDirs :: [String] -> String -> IO (String, B.ByteString)+readInDirs [] f = fail $ "cannot find file: " ++ f+readInDirs (d:ds) f = do+ let path = d</>f+ b <- doesFileExist path+ if b then+ (path,) <$> B.readFile path+ else+ readInDirs ds 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 lexer initState =+ evalParse (_collectTokens initState) undefined+ where+ _collectTokens :: ParseState b -> Parse b a [a]+ _collectTokens st = do+ let (_token, _st) = runParseUnsafe lexer st+ if eofToken _token+ then return [_token]+ else do+ _tokens <- _collectTokens _st+ return $ _token:_tokens++collectTokensSafe+ :: forall a b+ . (Loc b, Tok a, LastToken b a, Show a)+ => Parse b a a -> ParseState b -> Maybe [a]+collectTokensSafe lexer initState =+ evalParse (_collectTokens initState) undefined+ where+ _collectTokens :: ParseState b -> Parse b a (Maybe [a])+ _collectTokens st =+ case unParse lexer st of+ ParseOk _token _st ->+ if eofToken _token+ then return $ Just [_token]+ else do+ _mTokens <- _collectTokens _st+ case _mTokens of+ Just _tokens -> return $ Just $ _token:_tokens+ _ -> return Nothing+ _ -> return Nothing++fromParseResult :: (Show c) => ParseResult b c a -> Either ParseErrorSimple a+fromParseResult (ParseOk a _) = Right a+fromParseResult (ParseFailed err) =+ Left ParseErrorSimple+ { errorPos = errPos err+ , errorFilename = errFilename err+ , errorMsg = errMsg err ++ "\n" ++ tokenMsg (errLastToken err) }
− src/Language/Fortran/Parser/Any.hs
@@ -1,86 +0,0 @@-{-# 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-import Language.Fortran.Util.ModFile-import Language.Fortran.Version (FortranVersion(..), deduceFortranVersion)-import Language.Fortran.ParserMonad (ParseErrorSimple(..), fromParseResult)--import Language.Fortran.Parser.Fortran66 ( fortran66Parser, fortran66ParserWithModFiles )-import Language.Fortran.Parser.Fortran77 ( fortran77Parser, fortran77ParserWithModFiles- , extended77Parser, extended77ParserWithModFiles- , legacy77Parser, legacy77ParserWithModFiles )-import Language.Fortran.Parser.Fortran90 ( fortran90Parser, fortran90ParserWithModFiles )-import Language.Fortran.Parser.Fortran95 ( fortran95Parser, fortran95ParserWithModFiles )-import Language.Fortran.Parser.Fortran2003 ( fortran2003Parser, fortran2003ParserWithModFiles )--import qualified Data.ByteString.Char8 as B--type Parser = B.ByteString -> String -> Either ParseErrorSimple (ProgramFile A0)-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 = \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 =- 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 =- 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 =- 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 =- let parserF = parserWithModFilesVersions v- in parserF mods contents filename
+ src/Language/Fortran/Parser/Fixed/Fortran66.y view
@@ -0,0 +1,465 @@+-- -*- Mode: Haskell -*-+-- vim: ft=haskell+{+module Language.Fortran.Parser.Fixed.Fortran66+ ( programParser+ , blockParser+ , statementParser+ , expressionParser+ ) where++import Language.Fortran.Version+import Language.Fortran.Util.Position+import Language.Fortran.Parser.Monad+import Language.Fortran.Parser.Fixed.Lexer+import Language.Fortran.Parser.Fixed.Utils+import Language.Fortran.AST+import Language.Fortran.AST.RealLit++import Prelude hiding ( EQ, LT, GT ) -- Same constructors exist in the AST++}++%name programParser PROGRAM+%name blockParser BLOCK+%name statementParser STATEMENT+%name expressionParser EXPRESSION+%monad { LexAction }+%lexer { lexer } { TEOF _ }+%tokentype { Token }+%error { parseError }++%token+ '(' { TLeftPar _ }+ ')' { TRightPar _ }+ ',' { TComma _ }+ '.' { TDot _ }+ function { TFunction _ }+ subroutine { TSubroutine _ }+ blockData { TBlockData _ }+ end { TEnd _ }+ '=' { TOpAssign _ }+ assign { TAssign _ }+ to { TTo _ }+ goto { TGoto _ }+ if { TIf _ }+ call { TCall _ }+ return { TReturn _ }+ continue { TContinue _ }+ stop { TStop _ }+ pause { TPause _ }+ do { TDo _ }+ read { TRead _ }+ write { TWrite _ }+ rewind { TRewind _ }+ backspace { TBackspace _ }+ endfile { TEndfile _ }+ common { TCommon _ }+ equivalence { TEquivalence _ }+ external { TExternal _ }+ dimension { TDimension _ }+ integer { TType _ "integer" }+ real { TType _ "real" }+ doublePrecision { TType _ "doubleprecision" }+ logical { TType _ "logical" }+ complex { TType _ "complex" }+ data { TData _ }+ format { TFormat _ }+ blob { TBlob _ _ }+ int { TInt _ _ }+ exponent { TExponent _ _ }+ bool { TBool _ _ }+ '+' { TOpPlus _ }+ '-' { TOpMinus _ }+ '**' { TOpExp _ }+ '*' { TStar _ }+ '/' { TSlash _ }+ or { TOpOr _ }+ and { TOpAnd _ }+ not { TOpNot _ }+ '<' { TOpLT _ }+ '<=' { TOpLE _ }+ '>' { TOpGT _ }+ '>=' { TOpGE _ }+ '==' { TOpEQ _ }+ '!=' { TOpNE _ }+ id { TId _ _ }+ comment { TComment _ _ }+ hollerith { THollerith _ _ }+ label { TLabel _ _ }+ newline { TNewline _ }++%left or+%left and+%right not++%nonassoc '>' '<' '>=' '<=' '==' '!='+%nonassoc RELATIONAL++%left '+' '-'+%left '*' '/'+%right NEGATION+%right '**'++%%++-- This rule is to ignore leading whitespace+PROGRAM :: { ProgramFile A0 }+: NEWLINE PROGRAM_INNER { $2 }+| PROGRAM_INNER { $1 }++PROGRAM_INNER :: { ProgramFile A0 }+: PROGRAM_UNITS BLOCKS { ProgramFile (MetaInfo { miVersion = Fortran66, miFilename = "" }) (reverse $1 ++ convCmts (reverse $2)) }+| {- empty -} { ProgramFile (MetaInfo { miVersion = Fortran66, miFilename = "" }) [] }++PROGRAM_UNITS :: { [ ProgramUnit A0 ] }+: PROGRAM_UNITS MAIN_PROGRAM_UNIT { $2 : $1 }+| PROGRAM_UNITS BLOCKS OTHER_PROGRAM_UNIT { convCmts (reverse $2) ++ ($3 : $1) }+| MAIN_PROGRAM_UNIT { [ $1 ] }+| BLOCKS OTHER_PROGRAM_UNIT { convCmts (reverse $1) ++ [ $2 ] }++MAIN_PROGRAM_UNIT :: { ProgramUnit A0 }+: BLOCKS end MAYBE_NEWLINE+ { let blocks = reverse $1+ in PUMain () (getTransSpan $1 $2) Nothing blocks Nothing }++OTHER_PROGRAM_UNIT :: { ProgramUnit A0 }+: TYPE_SPEC function NAME MAYBE_ARGUMENTS NEWLINE BLOCKS end MAYBE_NEWLINE+ { PUFunction () (getTransSpan $1 $7) (Just $1) emptyPrefixSuffix $3 $4 Nothing (reverse $6) Nothing }+| function NAME MAYBE_ARGUMENTS NEWLINE BLOCKS end MAYBE_NEWLINE+ { PUFunction () (getTransSpan $1 $6) Nothing emptyPrefixSuffix $2 $3 Nothing (reverse $5) Nothing }+| subroutine NAME MAYBE_ARGUMENTS NEWLINE BLOCKS end MAYBE_NEWLINE+ { PUSubroutine () (getTransSpan $1 $6) emptyPrefixSuffix $2 $3 (reverse $5) Nothing }+| blockData NEWLINE BLOCKS end MAYBE_NEWLINE { PUBlockData () (getTransSpan $1 $4) Nothing (reverse $3) }++MAYBE_ARGUMENTS :: { Maybe (AList Expression A0) }+: '(' MAYBE_VARIABLES ')' { $2 }+| {- Nothing -} { Nothing }++NAME :: { Name } : id { let (TId _ name) = $1 in name }++BLOCKS :: { [ Block A0 ] }+: BLOCKS BLOCK { $2 : $1 }+| {- EMPTY -} { [ ] }++BLOCK :: { Block A0 }+: LABEL_IN_6COLUMN STATEMENT NEWLINE { BlStatement () (getTransSpan $1 $2) (Just $1) $2 }+| STATEMENT NEWLINE { BlStatement () (getSpan $1) Nothing $1 }+| comment NEWLINE { let (TComment s c) = $1 in BlComment () s (Comment c) }++MAYBE_NEWLINE :: { Maybe Token }+: NEWLINE { Just $1 }+| {- EMPTY -} { Nothing }++NEWLINE :: { Token }+: NEWLINE newline { $1 }+| newline { $1 }++STATEMENT :: { Statement A0 }+: LOGICAL_IF_STATEMENT { $1 }+| DO_STATEMENT { $1 }+| OTHER_EXECUTABLE_STATEMENT { $1 }+| NONEXECUTABLE_STATEMENT { $1 }++LOGICAL_IF_STATEMENT :: { Statement A0 }+: if '(' EXPRESSION ')' OTHER_EXECUTABLE_STATEMENT+ { StIfLogical () (getTransSpan $1 $5) $3 $5 }++DO_STATEMENT :: { Statement A0 }+: do LABEL_IN_STATEMENT DO_SPECIFICATION+ { StDo () (getTransSpan $1 $3) Nothing (Just $2) (Just $3) }++DO_SPECIFICATION :: { DoSpecification A0 }+: EXPRESSION_ASSIGNMENT_STATEMENT ',' INT_OR_VAR ',' INT_OR_VAR+ { DoSpecification () (getTransSpan $1 $5) $1 $3 (Just $5) }+| EXPRESSION_ASSIGNMENT_STATEMENT ',' INT_OR_VAR+ { DoSpecification () (getTransSpan $1 $3) $1 $3 Nothing }++INT_OR_VAR :: { Expression A0 }+: INTEGER_LITERAL { $1 }+| VARIABLE { $1 }++OTHER_EXECUTABLE_STATEMENT :: { Statement A0 }+: EXPRESSION_ASSIGNMENT_STATEMENT { $1 }+| assign LABEL_IN_STATEMENT to VARIABLE { StLabelAssign () (getTransSpan $1 $4) $2 $4 }+| goto LABEL_IN_STATEMENT { StGotoUnconditional () (getTransSpan $1 $2) $2 }+| goto VARIABLE LABELS_IN_STATEMENT { StGotoAssigned () (getTransSpan $1 $3) $2 (Just $3) }+| goto LABELS_IN_STATEMENT VARIABLE { StGotoComputed () (getTransSpan $1 $3) $2 $3 }+| if '(' EXPRESSION ')' LABEL_IN_STATEMENT ',' LABEL_IN_STATEMENT ',' LABEL_IN_STATEMENT { StIfArithmetic () (getTransSpan $1 $9) $3 $5 $7 $9 }+| call VARIABLE ARGUMENTS+ { StCall () (getTransSpan $1 $3) $2 (Just $3) }+| call VARIABLE { StCall () (getTransSpan $1 $2) $2 Nothing }+| return { StReturn () (getSpan $1) Nothing }+| continue { StContinue () $ getSpan $1 }+| stop INTEGER_LITERAL { StStop () (getTransSpan $1 $2) $ Just $2 }+| stop { StStop () (getSpan $1) Nothing }+| pause INTEGER_LITERAL { StPause () (getTransSpan $1 $2) $ Just $2 }+| pause { StPause () (getSpan $1) Nothing }+| rewind UNIT { StRewind2 () (getTransSpan $1 $2) $2 }+| backspace UNIT { StBackspace2 () (getTransSpan $1 $2) $2 }+| endfile UNIT { StEndfile2 () (getTransSpan $1 $2) $2 }+| write READ_WRITE_ARGUMENTS { let (cilist, iolist) = $2 in StWrite () (getTransSpan $1 $2) cilist iolist }+| read READ_WRITE_ARGUMENTS { let (cilist, iolist) = $2 in StRead () (getTransSpan $1 $2) cilist iolist }++EXPRESSION_ASSIGNMENT_STATEMENT :: { Statement A0 }+: ELEMENT '=' EXPRESSION { StExpressionAssign () (getTransSpan $1 $3) $1 $3 }++NONEXECUTABLE_STATEMENT :: { Statement A0 }+: external FUNCTION_NAMES { StExternal () (getTransSpan $1 $2) (aReverse $2) }+| dimension ARRAY_DECLARATORS { StDimension () (getTransSpan $1 $2) (aReverse $2) }+| common COMMON_GROUPS { StCommon () (getTransSpan $1 $2) (aReverse $2) }+| equivalence EQUIVALENCE_GROUPS { StEquivalence () (getTransSpan $1 $2) (aReverse $2) }+| data DATA_GROUPS { StData () (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+ { let TBlob s blob = $2 in StFormatBogus () (getTransSpan $1 s) blob }+| TYPE_SPEC DECLARATORS { StDeclaration () (getTransSpan $1 $2) $1 Nothing (aReverse $2) }++READ_WRITE_ARGUMENTS :: { (AList ControlPair A0, Maybe (AList Expression A0)) }+: '(' UNIT ')' IO_ELEMENTS { (AList () (getSpan $2) [ ControlPair () (getSpan $2) Nothing $2 ], Just (aReverse $4)) }+| '(' UNIT ',' FORM ')' IO_ELEMENTS { (AList () (getTransSpan $2 $4) [ ControlPair () (getSpan $2) Nothing $2, ControlPair () (getSpan $4) Nothing $4 ], Just (aReverse $6)) }+| '(' UNIT ')' { (AList () (getSpan $2) [ ControlPair () (getSpan $2) Nothing $2 ], Nothing) }+| '(' UNIT ',' FORM ')' { (AList () (getTransSpan $2 $4) [ ControlPair () (getSpan $2) Nothing $2, ControlPair () (getSpan $4) Nothing $4 ], Nothing) }++-- Not my terminology a VAR or an INT (probably positive) is defined as UNIT.+UNIT :: { Expression A0 }+: INTEGER_LITERAL { $1 }+| VARIABLE { $1 }++FORM :: { Expression A0 }+: VARIABLE { $1 }+| LABEL_IN_STATEMENT { $1 }++IO_ELEMENTS :: { AList Expression A0 }+: IO_ELEMENTS ',' IO_ELEMENT { setSpan (getTransSpan $1 $3) $ $3 `aCons` $1}+| IO_ELEMENT { AList () (getSpan $1) [ $1 ] }++IO_ELEMENT :: { Expression A0 }+: VARIABLE { $1 }+-- There should also be a caluse for variable names but not way to+-- differentiate it at this stage from VARIABLE. Hence, it is omitted to prevent+-- reduce/reduce conflict.+| SUBSCRIPT { $1 }+| '(' IO_ELEMENTS ',' DO_SPECIFICATION ')' { ExpImpliedDo () (getTransSpan $1 $5) $2 $4 }++ELEMENT :: { Expression A0 }+: VARIABLE { $1 }+| SUBSCRIPT { $1 }++DATA_GROUPS :: { AList DataGroup A0 }+: DATA_GROUPS ',' NAME_LIST '/' DATA_ITEMS '/' { setSpan (getTransSpan $1 $6) $ (DataGroup () (getTransSpan $3 $6) (aReverse $3) (aReverse $5)) `aCons` $1 }+| NAME_LIST '/' DATA_ITEMS '/' { AList () (getTransSpan $1 $4) [ DataGroup () (getTransSpan $1 $4) (aReverse $1) (aReverse $3) ] }++DATA_ITEMS :: { AList Expression A0 }+: DATA_ITEMS ',' DATA_ITEM { setSpan (getTransSpan $1 $3) $ $3 `aCons` $1}+| DATA_ITEM { AList () (getSpan $1) [ $1 ] }++DATA_ITEM :: { Expression A0 }+: INTEGER_LITERAL '*' DATA_ITEM_LEVEL1 { ExpBinary () (getTransSpan $1 $3) Multiplication $1 $3 }+| DATA_ITEM_LEVEL1 { $1 }++DATA_ITEM_LEVEL1 :: { Expression A0 }+: SIGNED_NUMERIC_LITERAL { $1 }+| COMPLEX_LITERAL { $1 }+| LOGICAL_LITERAL { $1 }+| HOLLERITH { $1 }++EQUIVALENCE_GROUPS :: { AList (AList Expression) A0 }+: EQUIVALENCE_GROUPS ',' '(' NAME_LIST ')' { setSpan (getTransSpan $1 $5) $ (setSpan (getTransSpan $3 $5) $ aReverse $4) `aCons` $1 }+| '(' NAME_LIST ')' { let s = (getTransSpan $1 $3) in AList () s [ setSpan s $ aReverse $2 ] }++COMMON_GROUPS :: { AList CommonGroup A0 }+: COMMON_GROUPS COMMON_GROUP { setSpan (getTransSpan $1 $2) $ $2 `aCons` $1 }+| INIT_COMMON_GROUP { AList () (getSpan $1) [ $1 ] }++COMMON_GROUP :: { CommonGroup A0 }+: COMMON_NAME DECLARATORS+ { CommonGroup () (getTransSpan $1 $2) (Just $1) $ aReverse $2 }+| '/' '/' DECLARATORS { CommonGroup () (getTransSpan $1 $3) Nothing $ aReverse $3 }++INIT_COMMON_GROUP :: { CommonGroup A0 }+: COMMON_NAME DECLARATORS+ { CommonGroup () (getTransSpan $1 $2) (Just $1) $ aReverse $2 }+| '/' '/' DECLARATORS { CommonGroup () (getTransSpan $1 $3) Nothing $ aReverse $3 }+| DECLARATORS { CommonGroup () (getSpan $1) Nothing $ aReverse $1 }++COMMON_NAME :: { Expression A0 }+: '/' VARIABLE '/' { setSpan (getTransSpan $1 $3) $2 }++NAME_LIST :: { AList Expression A0 }+: NAME_LIST ',' NAME_LIST_ELEMENT { setSpan (getTransSpan $1 $3) $ $3 `aCons` $1 }+| NAME_LIST_ELEMENT { AList () (getSpan $1) [ $1 ] }++NAME_LIST_ELEMENT :: { Expression A0 }+: VARIABLE { $1 }+| SUBSCRIPT { $1 }++-- Note that declarator lists in the F66 parser don't have initializers.+DECLARATORS :: { AList Declarator A0 }+: DECLARATORS ',' DECLARATOR { setSpan (getTransSpan $1 $3) $ $3 `aCons` $1 }+| DECLARATOR { AList () (getSpan $1) [ $1 ] }++DECLARATOR :: { Declarator A0 }+: ARRAY_DECLARATOR { $1 }+| VARIABLE_DECLARATOR { $1 }++ARRAY_DECLARATORS :: { AList Declarator A0 }+: ARRAY_DECLARATORS ',' ARRAY_DECLARATOR+ { setSpan (getTransSpan $1 $3) $ $3 `aCons` $1 }+| ARRAY_DECLARATOR+ { AList () (getSpan $1) [ $1 ] }++ARRAY_DECLARATOR :: { Declarator A0 }+: VARIABLE '(' DIMENSION_DECLARATORS ')'+ { Declarator () (getTransSpan $1 $4) $1 (ArrayDecl (aReverse $3)) Nothing Nothing }++DIMENSION_DECLARATORS :: { AList DimensionDeclarator A0 }+: DIMENSION_DECLARATORS ',' DIMENSION_DECLARATOR+ { setSpan (getTransSpan $1 $3) $ $3 `aCons` $1 }+| DIMENSION_DECLARATOR+ { AList () (getSpan $1) [ $1 ] }++DIMENSION_DECLARATOR :: { DimensionDeclarator A0 }+: EXPRESSION { DimensionDeclarator () (getSpan $1) Nothing (Just $1) }++VARIABLE_DECLARATOR :: { Declarator A0 }+: VARIABLE { Declarator () (getSpan $1) $1 ScalarDecl Nothing Nothing }++-- Here the procedure should be either a function or subroutine name, but+-- since they are syntactically identical at this stage subroutine names+-- are also emitted as function names.+FUNCTION_NAMES :: { AList Expression A0 }+: FUNCTION_NAMES ',' VARIABLE { setSpan (getTransSpan $1 $3) $ $3 `aCons` $1 }+| VARIABLE { AList () (getSpan $1) [ $1 ] }++ARGUMENTS :: { AList Argument A0 }+: ARGUMENTS_LEVEL1 ')' { setSpan (getTransSpan $1 $2) $ aReverse $1 }++ARGUMENTS_LEVEL1 :: { AList Argument A0 }+: ARGUMENTS_LEVEL1 ',' CALLABLE_EXPRESSION { setSpan (getTransSpan $1 $3) $ $3 `aCons` $1 }+| '(' CALLABLE_EXPRESSION { AList () (getTransSpan $1 $2) [ $2 ] }+| '(' { AList () (getSpan $1) [ ] }++-- Expression all by itself subsumes all other callable expressions.+CALLABLE_EXPRESSION :: { Argument A0 }+: HOLLERITH { Argument () (getSpan $1) Nothing (ArgExpr $1) }+| '(' VARIABLE ')'+ { let ExpValue _ _ (ValVariable v) = $2+ in Argument () (getTransSpan $1 $3) Nothing (ArgExprVar () (getSpan $2) v) }+| EXPRESSION { Argument () (getSpan $1) Nothing (ArgExpr $1) }++EXPRESSION :: { Expression A0 }+: EXPRESSION '+' EXPRESSION { ExpBinary () (getTransSpan $1 $3) Addition $1 $3 }+| EXPRESSION '-' EXPRESSION { ExpBinary () (getTransSpan $1 $3) Subtraction $1 $3 }+| EXPRESSION '*' EXPRESSION { ExpBinary () (getTransSpan $1 $3) Multiplication $1 $3 }+| EXPRESSION '/' EXPRESSION { ExpBinary () (getTransSpan $1 $3) Division $1 $3 }+| EXPRESSION '**' EXPRESSION { ExpBinary () (getTransSpan $1 $3) Exponentiation $1 $3 }+| ARITHMETIC_SIGN EXPRESSION %prec NEGATION { ExpUnary () (getTransSpan (fst $1) $2) (snd $1) $2 }+| EXPRESSION or EXPRESSION { ExpBinary () (getTransSpan $1 $3) Or $1 $3 }+| EXPRESSION and EXPRESSION { ExpBinary () (getTransSpan $1 $3) And $1 $3 }+| not EXPRESSION { ExpUnary () (getTransSpan $1 $2) Not $2 }+| EXPRESSION RELATIONAL_OPERATOR EXPRESSION %prec RELATIONAL { ExpBinary () (getTransSpan $1 $3) $2 $1 $3 }+| '(' EXPRESSION ')' { setSpan (getTransSpan $1 $3) $2 }+| INTEGER_LITERAL { $1 }+| REAL_LITERAL { $1 }+| COMPLEX_LITERAL { $1 }+| LOGICAL_LITERAL { $1 }+| SUBSCRIPT { $1 }+-- There should be FUNCTION_CALL here but as far as the parser is concerned it is same as SUBSCRIPT,+-- hence putting it here would cause a reduce/reduce conflict.+| VARIABLE { $1 }++RELATIONAL_OPERATOR :: { BinaryOp }+: '==' { EQ }+| '!=' { NE }+| '>' { GT }+| '>=' { GTE }+| '<' { LT }+| '<=' { LTE }++SUBSCRIPT :: { Expression A0 }+: VARIABLE '(' ')'+ { ExpFunctionCall () (getTransSpan $1 $3) $1 Nothing }+| VARIABLE '(' INDICIES ')'+ { ExpSubscript () (getTransSpan $1 $4) $1 (fromReverseList $3) }++INDICIES :: { [ Index A0 ] }+: INDICIES ',' EXPRESSION { IxSingle () (getSpan $3) Nothing $3 : $1 }+| EXPRESSION { [ IxSingle () (getSpan $1) Nothing $1 ] }++ARITHMETIC_SIGN :: { (SrcSpan, UnaryOp) }+: '-' { (getSpan $1, Minus) }+| '+' { (getSpan $1, Plus) }++MAYBE_VARIABLES :: { Maybe (AList Expression A0) }+: VARIABLES { Just $ fromReverseList $1 } | {- EMPTY -} { Nothing }++VARIABLES :: { [ Expression A0 ] }+: VARIABLES ',' VARIABLE { $3 : $1 } | VARIABLE { [ $1 ] }++-- This may also be used to parse a function name, or an array name. Since when+-- are valid options in a production there is no way of differentiating them at+-- this stage.+-- This at least reduces reduce/reduce conflicts.+VARIABLE :: { Expression A0 }+: id { ExpValue () (getSpan $1) $ let (TId _ s) = $1 in ValVariable s }++SIGNED_INTEGER_LITERAL :: { Expression A0 }+: ARITHMETIC_SIGN INTEGER_LITERAL { ExpUnary () (getTransSpan (fst $1) $2) (snd $1) $2 }+| INTEGER_LITERAL { $1 }++INTEGER_LITERAL :: { Expression A0 }+: int { ExpValue () (getSpan $1) $ let (TInt _ i) = $1 in ValInteger i Nothing }++SIGNED_REAL_LITERAL :: { Expression A0 }+: ARITHMETIC_SIGN REAL_LITERAL { ExpUnary () (getTransSpan (fst $1) $2) (snd $1) $2 }+| REAL_LITERAL { $1 }++REAL_LITERAL :: { Expression A0 }+: int EXPONENT { makeRealLit (Just $1) Nothing Nothing (Just $2) }+| int '.' MAYBE_EXPONENT { makeRealLit (Just $1) (Just $2) Nothing $3 }+| '.' int MAYBE_EXPONENT { makeRealLit Nothing (Just $1) (Just $2) $3 }+| int '.' int MAYBE_EXPONENT { makeRealLit (Just $1) (Just $2) (Just $3) $4 }++MAYBE_EXPONENT :: { Maybe (SrcSpan, String) }+: EXPONENT { Just $1 }+| {-EMPTY-} { Nothing }++EXPONENT :: { (SrcSpan, String) }+: exponent { let (TExponent s exp) = $1 in (s, exp) }++SIGNED_NUMERIC_LITERAL :: { Expression A0 }+: SIGNED_INTEGER_LITERAL { $1 }+| SIGNED_REAL_LITERAL { $1 }++COMPLEX_LITERAL :: { Expression A0 }+: '(' SIGNED_NUMERIC_LITERAL ',' SIGNED_NUMERIC_LITERAL ')' { ExpValue () (getTransSpan $1 $5) (ValComplex $2 $4)}++LOGICAL_LITERAL :: { Expression A0 }+: bool { let TBool s b = $1 in ExpValue () s $ ValLogical b Nothing }++HOLLERITH :: { Expression A0 }+: hollerith { ExpValue () (getSpan $1) $ let (THollerith _ h) = $1 in ValHollerith h }++LABELS_IN_STATEMENT :: { AList Expression A0 }+: LABELS_IN_STATEMENT_LEVEL1 ')' { setSpan (getTransSpan $1 $2) $ aReverse $1 }++LABELS_IN_STATEMENT_LEVEL1 :: { AList Expression A0 }+: LABELS_IN_STATEMENT_LEVEL1 ',' LABEL_IN_STATEMENT { setSpan (getTransSpan $1 $3) $ $3 `aCons` $1 }+| '(' LABEL_IN_STATEMENT { AList () (getTransSpan $1 $2) [ $2 ] }++-- Labels that occur in the first 6 columns+LABEL_IN_6COLUMN :: { Expression A0 }+: label { ExpValue () (getSpan $1) (let (TLabel _ l) = $1 in ValInteger l Nothing) }++-- Labels that occur in statements+LABEL_IN_STATEMENT :: { Expression A0 }+: int { ExpValue () (getSpan $1) (let (TInt _ l) = $1 in ValInteger l Nothing) }++TYPE_SPEC :: { TypeSpec A0 }+: integer { TypeSpec () (getSpan $1) TypeInteger Nothing }+| real { TypeSpec () (getSpan $1) TypeReal Nothing }+| doublePrecision { TypeSpec () (getSpan $1) TypeDoublePrecision Nothing }+| logical { TypeSpec () (getSpan $1) TypeLogical Nothing }+| complex { TypeSpec () (getSpan $1) TypeComplex Nothing }
+ src/Language/Fortran/Parser/Fixed/Fortran77.y view
@@ -0,0 +1,977 @@+-- -*- Mode: Haskell -*-+-- vim: ft=haskell+{+module Language.Fortran.Parser.Fixed.Fortran77+ ( programParser+ , blockParser+ , statementParser+ , expressionParser+ , includesParser+ ) where++import Language.Fortran.Version+import Language.Fortran.Util.Position+import Language.Fortran.Parser.Monad+import Language.Fortran.Parser.Fixed.Lexer+import Language.Fortran.Parser.Fixed.Utils+import Language.Fortran.AST+import Language.Fortran.AST.RealLit++import Prelude hiding ( EQ, LT, GT ) -- Same constructors exist in the AST+import Data.Maybe ( isNothing, fromJust )++}++%name programParser PROGRAM+%name blockParser BLOCK+%name statementParser STATEMENT+%name expressionParser EXPRESSION+%name includesParser INCLUDES+%monad { LexAction }+%lexer { lexer } { TEOF _ }+%tokentype { Token }+%error { parseError }++%token+ '(' { TLeftPar _ }+ ')' { TRightPar _ }+ '(/' { TLeftArrayPar _ }+ '/)' { TRightArrayPar _ }+ ',' { TComma _ }+ '.' { TDot _ }+ '%' { TPercent _ }+ ':' { TColon _ }+ include { TInclude _ }+ program { TProgram _ }+ function { TFunction _ }+ subroutine { TSubroutine _ }+ endprogram { TEndProgram _ }+ endfunction { TEndFunction _ }+ endsubroutine { TEndSubroutine _ }+ blockData { TBlockData _ }+ structure { TStructure _ }+ union { TUnion _ }+ map { TMap _ }+ endstructure { TEndStructure _ }+ endunion { TEndUnion _ }+ endmap { TEndMap _ }+ record { TRecord _ }+ end { TEnd _ }+ '=' { TOpAssign _ }+ assign { TAssign _ }+ to { TTo _ }+ goto { TGoto _ }+ if { TIf _ }+ then { TThen _ }+ else { TElse _ }+ elsif { TElsif _ }+ endif { TEndif _ }+ call { TCall _ }+ return { TReturn _ }+ save { TSave _ }+ continue { TContinue _ }+ stop { TStop _ }+ exit { TExit _ }+ cycle { TCycle _ }+ case { TCase _ }+ selectcase { TSelectCase _ }+ endselect { TEndSelect _ }+ casedefault { TCaseDefault _ }+ pause { TPause _ }+ do { TDo _ }+ doWhile { TDoWhile _ }+ while { TWhile _ }+ enddo { TEndDo _ }+ read { TRead _ }+ write { TWrite _ }+ print { TPrint _ }+ typeprint { TTypePrint _ }+ open { TOpen _ }+ close { TClose _ }+ inquire { TInquire _ }+ rewind { TRewind _ }+ backspace { TBackspace _ }+ endfile { TEndfile _ }+ common { TCommon _ }+ equivalence { TEquivalence _ }+ external { TExternal _ }+ dimension { TDimension _ }+ byte { TType _ "byte" }+ character { TType _ "character" }+ integer { TType _ "integer" }+ real { TType _ "real" }+ doublePrecision { TType _ "doubleprecision" }+ logical { TType _ "logical" }+ complex { TType _ "complex" }+ doubleComplex { TType _ "doublecomplex" }+ intrinsic { TIntrinsic _ }+ implicit { TImplicit _ }+ parameter { TParameter _ }+ pointer { TPointer _ }+ entry { TEntry _ }+ none { TNone _ }+ data { TData _ }+ automatic { TAutomatic _ }+ static { TStatic _ }+ format { TFormat _ }+ blob { TBlob _ _ }+ int { TInt _ _ }+ boz { TBozLiteral _ _ }+ exponent { TExponent _ _ }+ bool { TBool _ _ }+ '+' { TOpPlus _ }+ '-' { TOpMinus _ }+ '**' { TOpExp _ }+ '*' { TStar _ }+ '/' { TSlash _ }+ '&' { TAmpersand _ }+ eqv { TOpEquivalent _ }+ neqv { TOpNotEquivalent _ }+ or { TOpOr _ }+ and { TOpAnd _ }+ xor { TOpXOr _ }+ not { TOpNot _ }+ '<' { TOpLT _ }+ '<=' { TOpLE _ }+ '>' { TOpGT _ }+ '>=' { TOpGE _ }+ '==' { TOpEQ _ }+ '!=' { TOpNE _ }+ id { TId _ _ }+ comment { TComment _ _ }+ hollerith { THollerith _ _ }+ string { TString _ _ }+ label { TLabel _ _ }+ newline { TNewline _ }++%left eqv neqv xor+%left or+%left and+%right not++%nonassoc '>' '<' '>=' '<=' '==' '!='+%nonassoc RELATIONAL++%left CONCAT++%left '+' '-'+%left '*' '/'+%right NEGATION+%right '**'++%%++maybe(p)+: p { Just $1 }+| {- empty -} { Nothing }++rev_list1(p)+: p { [$1] }+| rev_list1(p) p { $2 : $1 }++rev_list(p)+: rev_list1(p) { $1 }+| {- empty -} { [] }++list1(p)+: rev_list1(p) { reverse $1 }++list(p)+: rev_list(p) { reverse $1 }++-- This rule is to ignore leading whitespace+PROGRAM :: { ProgramFile A0 }+: NEWLINE PROGRAM_INNER { $2 }+| PROGRAM_INNER { $1 }++PROGRAM_INNER :: { ProgramFile A0 }+: PROGRAM_UNITS { ProgramFile (MetaInfo { miVersion = Fortran77, miFilename = "" }) (reverse $1) }+| {- empty -} { ProgramFile (MetaInfo { miVersion = Fortran77, miFilename = "" }) [] }++PROGRAM_UNITS :: { [ ProgramUnit A0 ] }+: PROGRAM_UNITS maybe(LABEL_IN_6COLUMN) PROGRAM_UNIT maybe(NEWLINE) { $3 : $1 }+| maybe(LABEL_IN_6COLUMN) PROGRAM_UNIT maybe(NEWLINE) { [ $2 ] }++PROGRAM_UNIT :: { ProgramUnit A0 }+: program NAME NEWLINE BLOCKS ENDPROG+ { PUMain () (getTransSpan $1 $5) (Just $2) (reverse $4) Nothing }+| TYPE_SPEC function NAME MAYBE_ARGUMENTS NEWLINE BLOCKS ENDFUN+ { PUFunction () (getTransSpan $1 $7) (Just $1) emptyPrefixSuffix $3 $4 Nothing (reverse $6) Nothing }+| function NAME MAYBE_ARGUMENTS NEWLINE BLOCKS ENDFUN+ { PUFunction () (getTransSpan $1 $6) Nothing emptyPrefixSuffix $2 $3 Nothing (reverse $5) Nothing }+| subroutine NAME MAYBE_ARGUMENTS NEWLINE BLOCKS ENDSUB+ { PUSubroutine () (getTransSpan $1 $6) emptyPrefixSuffix $2 $3 (reverse $5) Nothing }+| blockData NEWLINE BLOCKS END { PUBlockData () (getTransSpan $1 $4) Nothing (reverse $3) }+| blockData NAME NEWLINE BLOCKS END { PUBlockData () (getTransSpan $1 $5) (Just $2) (reverse $4) }+| comment { let (TComment s c) = $1 in PUComment () s (Comment c) }++END :: { Token }+: end { $1 }+| LABEL_IN_6COLUMN end { $2 }++ENDPROG :: { Token }+: END { $1 }+| endprogram MAYBE_ID { $1 }+| LABEL_IN_6COLUMN endprogram MAYBE_ID { $2 }++ENDFUN :: { Token }+: END { $1 }+| endfunction MAYBE_ID { $1 }+| LABEL_IN_6COLUMN endfunction MAYBE_ID { $2 }++ENDSUB :: { Token }+: END { $1 }+| endsubroutine MAYBE_ID { $1 }+| LABEL_IN_6COLUMN endsubroutine MAYBE_ID { $2 }++MAYBE_ARGUMENTS :: { Maybe (AList Expression A0) }+: '(' MAYBE_VARIABLES ')' { $2 }+| {- Nothing -} { Nothing }++MAYBE_ID :: { Maybe Name }+: id { let (TId _ name) = $1 in Just name }+| {- empty -} { Nothing }++NAME :: { Name } : id { let (TId _ name) = $1 in name }++INCLUDES :: { [ Block A0 ] }+: maybe(NEWLINE) list(BLOCK) { $2 }++BLOCKS :: { [ Block A0 ] }+: BLOCKS BLOCK { $2 : $1 }+| {- EMPTY -} { [ ] }++BLOCK :: { Block A0 }+: IF_BLOCK NEWLINE { $1 }+| LABEL_IN_6COLUMN STATEMENT NEWLINE { BlStatement () (getTransSpan $1 $2) (Just $1) $2 }+| STATEMENT NEWLINE { BlStatement () (getSpan $1) Nothing $1 }+| COMMENT_BLOCK { $1 }++IF_BLOCK :: { Block A0 }+: if '(' EXPRESSION ')' then NEWLINE BLOCKS ELSE_BLOCKS {+ let (endSpan, endLabel, conds, blocks) = $8+ in BlIf () (getTransSpan $1 endSpan) Nothing Nothing ((Just $3):conds) ((reverse $7):blocks) endLabel+ }+| LABEL_IN_6COLUMN if '(' EXPRESSION ')' then NEWLINE BLOCKS ELSE_BLOCKS {+ let (endSpan, endLabel, conds, blocks) = $9+ in BlIf () (getTransSpan $1 endSpan) (Just $1) Nothing ((Just $4):conds) ((reverse $8):blocks) endLabel+ }++ELSE_BLOCKS :: { (SrcSpan, Maybe (Expression A0), [Maybe (Expression A0)], [[Block A0]]) }+: maybe(LABEL_IN_6COLUMN) elsif '(' EXPRESSION ')' then NEWLINE BLOCKS ELSE_BLOCKS+ { let (endSpan, endLabel, conds, blocks) = $9+ in (endSpan, endLabel, Just $4 : conds, reverse $8 : blocks) }+| maybe(LABEL_IN_6COLUMN) else NEWLINE BLOCKS maybe(LABEL_IN_6COLUMN) endif+ { (getSpan $6, $5, [Nothing], [reverse $4]) }+| maybe(LABEL_IN_6COLUMN) endif { (getSpan $2, $1, [], []) }++COMMENT_BLOCK :: { Block A0 }+: comment NEWLINE { let (TComment s c) = $1 in BlComment () s (Comment c) }++NEWLINE :: { Token }+: NEWLINE newline { $1 }+| newline { $1 }++STATEMENT :: { Statement A0 }+: LOGICAL_IF_STATEMENT { $1 }+| DO_STATEMENT { $1 }+| EXECUTABLE_STATEMENT { $1 }+| NONEXECUTABLE_STATEMENT { $1 }++LOGICAL_IF_STATEMENT :: { Statement A0 }+: if '(' EXPRESSION ')' EXECUTABLE_STATEMENT { StIfLogical () (getTransSpan $1 $5) $3 $5 }++DO_STATEMENT :: { Statement A0 }+: do LABEL_IN_STATEMENT DO_SPECIFICATION { StDo () (getTransSpan $1 $3) Nothing (Just $2) (Just $3) }+| do LABEL_IN_STATEMENT ',' DO_SPECIFICATION { StDo () (getTransSpan $1 $4) Nothing (Just $2) (Just $4) }+| do DO_SPECIFICATION { StDo () (getTransSpan $1 $2) Nothing Nothing (Just $2) }+| do { StDo () (getSpan $1) Nothing Nothing Nothing }++DO_SPECIFICATION :: { DoSpecification A0 }+: EXPRESSION_ASSIGNMENT_STATEMENT ',' EXPRESSION ',' EXPRESSION { DoSpecification () (getTransSpan $1 $5) $1 $3 (Just $5) }+| EXPRESSION_ASSIGNMENT_STATEMENT ',' EXPRESSION { DoSpecification () (getTransSpan $1 $3) $1 $3 Nothing }++EXECUTABLE_STATEMENT :: { Statement A0 }+: EXPRESSION_ASSIGNMENT_STATEMENT { $1 }+| assign LABEL_IN_STATEMENT to VARIABLE { StLabelAssign () (getTransSpan $1 $4) $2 $4 }+| GOTO_STATEMENT { $1 }+| if '(' EXPRESSION ')' LABEL_IN_STATEMENT ',' LABEL_IN_STATEMENT ',' LABEL_IN_STATEMENT { StIfArithmetic () (getTransSpan $1 $9) $3 $5 $7 $9 }+| doWhile '(' EXPRESSION ')'+ { StDoWhile () (getTransSpan $1 $4) Nothing Nothing $3 }+| do LABEL_IN_STATEMENT while '(' EXPRESSION ')'+ { StDoWhile () (getTransSpan $1 $6) Nothing (Just $2) $5 }+| do LABEL_IN_STATEMENT ',' while '(' EXPRESSION ')'+ { StDoWhile () (getTransSpan $1 $7) Nothing (Just $2) $6 }+| enddo { StEnddo () (getSpan $1) Nothing }+| call VARIABLE ARGUMENTS+ { StCall () (getTransSpan $1 $3) $2 $ Just $3 }+| call VARIABLE { StCall () (getTransSpan $1 $2) $2 Nothing }+| return { StReturn () (getSpan $1) Nothing }+| return EXPRESSION { StReturn () (getTransSpan $1 $2) $ Just $2 }+| save SAVE_ARGS { StSave () (getSpan ($1, $2)) $2 }+| continue { StContinue () $ getSpan $1 }+| stop INTEGER_OR_STRING { StStop () (getTransSpan $1 $2) $ Just $2 }+| stop { StStop () (getSpan $1) Nothing }+| exit { StExit () (getSpan $1) Nothing }+| cycle { StCycle () (getSpan $1) Nothing }+| pause INTEGER_OR_STRING { StPause () (getTransSpan $1 $2) $ Just $2 }+| pause { StPause () (getSpan $1) Nothing }+| selectcase '(' EXPRESSION ')'+ { StSelectCase () (getTransSpan $1 $4) Nothing $3 }+| casedefault { StCase () (getSpan $1) Nothing Nothing }+| casedefault id+ { let TId s id = $2 in StCase () (getTransSpan $1 s) (Just id) Nothing }+| case '(' INDICIES ')'+ { StCase () (getTransSpan $1 $4) Nothing (Just $ fromReverseList $3) }+| case '(' INDICIES ')' id+ { let TId s id = $5+ in StCase () (getTransSpan $1 s) (Just id) (Just $ fromReverseList $3) }+| endselect { StEndcase () (getSpan $1) Nothing }+| endselect id+ { let TId s id = $2 in StEndcase () (getTransSpan $1 s) (Just id) }+-- IO Statements+| read CILIST IN_IOLIST { StRead () (getTransSpan $1 $3) $2 (Just $ aReverse $3) }+| read CILIST { StRead () (getTransSpan $1 $2) $2 Nothing }+| read FORMAT_ID ',' IN_IOLIST { StRead2 () (getTransSpan $1 $4) $2 (Just $ aReverse $4) }+| read FORMAT_ID { StRead2 () (getTransSpan $1 $2) $2 Nothing }+| write CILIST OUT_IOLIST { StWrite () (getTransSpan $1 $3) $2 (Just $ aReverse $3) }+| write CILIST { StWrite () (getTransSpan $1 $2) $2 Nothing }+| print FORMAT_ID ',' OUT_IOLIST { StPrint () (getTransSpan $1 $4) $2 (Just $ aReverse $4) }+| print FORMAT_ID { StPrint () (getTransSpan $1 $2) $2 Nothing }+| typeprint FORMAT_ID ',' OUT_IOLIST { StTypePrint () (getTransSpan $1 $4) $2 (Just $ aReverse $4) }+| typeprint FORMAT_ID { StTypePrint () (getTransSpan $1 $2) $2 Nothing }+| open CILIST { StOpen () (getTransSpan $1 $2) $2 }+| close CILIST { StClose () (getTransSpan $1 $2) $2 }+| inquire CILIST { StInquire () (getTransSpan $1 $2) $2 }+| rewind CILIST { StRewind () (getTransSpan $1 $2) $2 }+| rewind UNIT { StRewind2 () (getTransSpan $1 $2) $2 }+| endfile CILIST { StEndfile () (getTransSpan $1 $2) $2 }+| endfile UNIT { StEndfile2 () (getTransSpan $1 $2) $2 }+| backspace CILIST { StBackspace () (getTransSpan $1 $2) $2 }+| backspace UNIT { StBackspace2 () (getTransSpan $1 $2) $2 }++FORMAT_ID :: { Expression A0 }+: FORMAT_ID '/' '/' FORMAT_ID %prec CONCAT { ExpBinary () (getTransSpan $1 $4) Concatenation $1 $4 }+| INTEGER_LITERAL { $1 }+-- There should be FUNCTION_CALL here but as far as the parser is concerned it is same as SUBSCRIPT,+-- hence putting it here would cause a reduce/reduce conflict.+| SUBSCRIPT { $1 }+| '*' { ExpValue () (getSpan $1) ValStar }++UNIT :: { Expression A0 }+: INTEGER_LITERAL { $1 }+| SUBSCRIPT { $1 }+| '*' { ExpValue () (getSpan $1) ValStar }++-- A crude approximation that makes parsing easy. Individual key value pairs+-- should be checket later on.+CILIST :: { AList ControlPair A0 }+: '(' UNIT ',' FORMAT_ID ',' CILIST_PAIRS ')' {+ let { cp1 = ControlPair () (getSpan $2) Nothing $2;+ cp2 = ControlPair () (getSpan $4) Nothing $4 }+ in setSpan (getTransSpan $1 $7) $ cp1 `aCons` cp2 `aCons` aReverse $6+ }+| '(' UNIT ',' FORMAT_ID ')' {+ let { cp1 = ControlPair () (getSpan $2) Nothing $2;+ cp2 = ControlPair () (getSpan $4) Nothing $4 }+ in AList () (getTransSpan $1 $5) [ cp1, cp2 ]+ }+| '(' UNIT ',' CILIST_PAIRS ')' {+ let cp1 = ControlPair () (getSpan $2) Nothing $2+ in setSpan (getTransSpan $1 $5) $ cp1 `aCons` aReverse $4+ }+| '(' UNIT ')' {+ let cp1 = ControlPair () (getSpan $2) Nothing $2+ in AList () (getTransSpan $1 $3) [ cp1 ]+ }+| '(' CILIST_PAIRS ')' { setSpan (getTransSpan $1 $3) $ aReverse $2 }++CILIST_PAIRS :: { AList ControlPair A0 }+: CILIST_PAIRS ',' CILIST_PAIR { setSpan (getTransSpan $1 $3) $ $3 `aCons` $1 }+| CILIST_PAIR { AList () (getSpan $1) [ $1 ] }++CILIST_PAIR :: { ControlPair A0 }+: id '=' CILIST_ELEMENT { let (TId s id) = $1 in ControlPair () (getTransSpan s $3) (Just id) $3 }++CILIST_ELEMENT :: { Expression A0 }+: CI_EXPRESSION { $1 }+| '*' { ExpValue () (getSpan $1) ValStar }++CI_EXPRESSION :: { Expression A0 }+: CI_EXPRESSION '+' CI_EXPRESSION { ExpBinary () (getTransSpan $1 $3) Addition $1 $3 }+| CI_EXPRESSION '-' CI_EXPRESSION { ExpBinary () (getTransSpan $1 $3) Subtraction $1 $3 }+| CI_EXPRESSION '*' CI_EXPRESSION { ExpBinary () (getTransSpan $1 $3) Multiplication $1 $3 }+| CI_EXPRESSION '/' CI_EXPRESSION { ExpBinary () (getTransSpan $1 $3) Division $1 $3 }+| CI_EXPRESSION '**' CI_EXPRESSION { ExpBinary () (getTransSpan $1 $3) Exponentiation $1 $3 }+| CI_EXPRESSION '/' '/' CI_EXPRESSION %prec CONCAT { ExpBinary () (getTransSpan $1 $4) Concatenation $1 $4 }+| ARITHMETIC_SIGN CI_EXPRESSION %prec NEGATION { ExpUnary () (getTransSpan (fst $1) $2) (snd $1) $2 }+| CI_EXPRESSION or CI_EXPRESSION { ExpBinary () (getTransSpan $1 $3) Or $1 $3 }+| CI_EXPRESSION and CI_EXPRESSION { ExpBinary () (getTransSpan $1 $3) And $1 $3 }+| CI_EXPRESSION xor CI_EXPRESSION { ExpBinary () (getTransSpan $1 $3) XOr $1 $3 }+| not CI_EXPRESSION { ExpUnary () (getTransSpan $1 $2) Not $2 }+| CI_EXPRESSION eqv CI_EXPRESSION { ExpBinary () (getTransSpan $1 $3) Equivalent $1 $3 }+| CI_EXPRESSION neqv CI_EXPRESSION { ExpBinary () (getTransSpan $1 $3) NotEquivalent $1 $3 }+| CI_EXPRESSION RELATIONAL_OPERATOR CI_EXPRESSION %prec RELATIONAL { ExpBinary () (getTransSpan $1 $3) $2 $1 $3 }+| '(' CI_EXPRESSION ')' { setSpan (getTransSpan $1 $3) $2 }+| INTEGER_LITERAL { $1 }+| LOGICAL_LITERAL { $1 }+-- There should be FUNCTION_CALL here but as far as the parser is concerned it is same as SUBSCRIPT,+-- hence putting it here would cause a reduce/reduce conflict.+| SUBSCRIPT { $1 }++-- Input IOList used in read like statements is much more restrictive as it+-- doesn't make sense to read into an integer.+-- While the output list can be an arbitrary expression. Hence, the grammar+-- rule separation.++IN_IOLIST :: { AList Expression A0 }+: IN_IOLIST ',' IN_IO_ELEMENT { setSpan (getTransSpan $1 $3) $ $3 `aCons` $1}+| IN_IO_ELEMENT { AList () (getSpan $1) [ $1 ] }++IN_IO_ELEMENT :: { Expression A0 }+: SUBSCRIPT { $1 }+| '(' IN_IOLIST ',' DO_SPECIFICATION ')' { ExpImpliedDo () (getTransSpan $1 $5) (aReverse $2) $4 }++OUT_IOLIST :: { AList Expression A0 }+: OUT_IOLIST ',' EXPRESSION { setSpan (getTransSpan $1 $3) $ $3 `aCons` $1}+| EXPRESSION { AList () (getSpan $1) [ $1 ] }++SAVE_ARGS :: { Maybe (AList Expression A0) }+: SAVE_ARGS_LEVEL1 { Just $ fromReverseList $1 }+| {-EMPTY-} { Nothing }++SAVE_ARGS_LEVEL1 :: { [ Expression A0 ] }+: SAVE_ARGS_LEVEL1 ',' SAVE_ARG { $3 : $1 }+| SAVE_ARG { [ $1 ] }++SAVE_ARG :: { Expression A0 }+: COMMON_NAME { $1 } | VARIABLE { $1 }++INTEGER_OR_STRING :: { Expression A0 } : STRING { $1 } | INTEGER_LITERAL { $1 }++GOTO_STATEMENT :: { Statement A0 }+: goto LABEL_IN_STATEMENT { StGotoUnconditional () (getTransSpan $1 $2) $2 }+| goto VARIABLE { StGotoAssigned () (getTransSpan $1 $2) $2 Nothing }+| goto VARIABLE LABELS_IN_STATEMENT { StGotoAssigned () (getTransSpan $1 $3) $2 (Just $3) }+| goto VARIABLE ',' LABELS_IN_STATEMENT { StGotoAssigned () (getTransSpan $1 $4) $2 (Just $4) }+| goto LABELS_IN_STATEMENT EXPRESSION { StGotoComputed () (getTransSpan $1 $3) $2 $3 }+| goto LABELS_IN_STATEMENT ',' EXPRESSION { StGotoComputed () (getTransSpan $1 $4) $2 $4 }++EXPRESSION_ASSIGNMENT_STATEMENT :: { Statement A0 }+: ELEMENT '=' EXPRESSION { StExpressionAssign () (getTransSpan $1 $3) $1 $3 }++NONEXECUTABLE_STATEMENT :: { Statement A0 }+: external FUNCTION_NAMES { StExternal () (getTransSpan $1 $2) (aReverse $2) }+| intrinsic FUNCTION_NAMES { StIntrinsic () (getTransSpan $1 $2) (aReverse $2) }+| dimension INITIALIZED_ARRAY_DECLARATORS { StDimension () (getTransSpan $1 $2) (aReverse $2) }+| common COMMON_GROUPS { StCommon () (getTransSpan $1 $2) (aReverse $2) }+| equivalence EQUIVALENCE_GROUPS { StEquivalence () (getTransSpan $1 $2) (aReverse $2) }+| pointer POINTER_LIST { StPointer () (getTransSpan $1 $2) (fromReverseList $2) }+| data DATA_GROUPS { StData () (getTransSpan $1 $2) (fromReverseList $2) }+| automatic INITIALIZED_DECLARATORS { StAutomatic () (getTransSpan $1 $2) (aReverse $2) }+| static INITIALIZED_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+ { let TBlob s blob = $2 in StFormatBogus () (getTransSpan $1 s) blob }+| DECLARATION_STATEMENT { $1 }+| implicit none { StImplicit () (getTransSpan $1 $2) Nothing }+| implicit IMP_LISTS { StImplicit () (getTransSpan $1 $2) $ Just $ aReverse $2 }+| parameter '(' PARAMETER_ASSIGNMENTS ')'+ { StParameter () (getTransSpan $1 $4) $ fromReverseList $3 }+| entry VARIABLE { StEntry () (getTransSpan $1 $2) $2 Nothing Nothing }+| entry VARIABLE ENTRY_ARGS { StEntry () (getTransSpan $1 $3) $2 (Just $3) Nothing }+| include STRING { StInclude () (getTransSpan $1 $2) $2 Nothing }+| structure MAYBE_NAME NEWLINE STRUCTURE_DECLARATIONS endstructure+ { StStructure () (getTransSpan $1 $5) $2 (fromReverseList $4) }++MAYBE_NAME :: { Maybe Name }+: '/' NAME '/' { Just $2 }+| {- empty -} { Nothing }++STRUCTURE_DECLARATIONS :: { [StructureItem A0] }+: STRUCTURE_DECLARATIONS STRUCTURE_DECLARATION_STATEMENT+ { if isNothing $2 then $1 else fromJust $2 : $1 }+| STRUCTURE_DECLARATION_STATEMENT { if isNothing $1 then [] else [fromJust $1] }++STRUCTURE_DECLARATION_STATEMENT :: { Maybe (StructureItem A0) }+: DECLARATION_STATEMENT NEWLINE+ { let StDeclaration () s t attrs decls = $1+ in Just $ StructFields () s t attrs decls }+| union NEWLINE UNION_MAPS endunion NEWLINE+ { Just $ StructUnion () (getTransSpan $1 $5) (fromReverseList $3) }+| structure MAYBE_NAME NAME NEWLINE STRUCTURE_DECLARATIONS endstructure NEWLINE+ { Just $ StructStructure () (getTransSpan $1 $7) $2 $3 (fromReverseList $5) }+| comment NEWLINE { Nothing }++UNION_MAPS :: { [ UnionMap A0 ] }+: UNION_MAPS UNION_MAP { if isNothing $2 then $1 else fromJust $2 : $1 }+| UNION_MAP { if isNothing $1 then [] else [fromJust $1] }++UNION_MAP :: { Maybe (UnionMap A0) }+: map NEWLINE STRUCTURE_DECLARATIONS endmap NEWLINE+ { Just $ UnionMap () (getTransSpan $1 $5) (fromReverseList $3) }+| comment NEWLINE { Nothing }++ENTRY_ARGS :: { AList Expression A0 }+: ENTRY_ARGS_LEVEL1 ')' { setSpan (getTransSpan $1 $2) $ aReverse $1 }++ENTRY_ARGS_LEVEL1 :: { AList Expression A0 }+: ENTRY_ARGS_LEVEL1 ',' ENTRY_ARG { setSpan (getTransSpan $1 $3) $ $3 `aCons` $1 }+| '(' ENTRY_ARG { AList () (getTransSpan $1 $2) [ $2 ] }+| '(' { AList () (getSpan $1) [ ] }++ENTRY_ARG :: { Expression A0 }+: VARIABLE { $1 }+| '*' { ExpValue () (getSpan $1) ValStar }++PARAMETER_ASSIGNMENTS :: { [ Declarator A0 ] }+: PARAMETER_ASSIGNMENTS ',' PARAMETER_ASSIGNMENT { $3 : $1 }+| PARAMETER_ASSIGNMENT { [ $1 ] }++PARAMETER_ASSIGNMENT :: { Declarator A0 }+: VARIABLE '=' CONSTANT_EXPRESSION+ { Declarator () (getTransSpan $1 $3) $1 ScalarDecl Nothing (Just $3) }++DECLARATION_STATEMENT :: { Statement A0 }+: TYPE_SPEC maybe(',') INITIALIZED_DECLARATORS+ { StDeclaration () (getTransSpan $1 $3) $1 Nothing (aReverse $3) }++IMP_LISTS :: { AList ImpList A0 }+: IMP_LISTS ',' IMP_LIST { setSpan (getTransSpan $1 $3) $ $3 `aCons` $1 }+| IMP_LIST { AList () (getSpan $1) [ $1 ] }++IMP_LIST :: { ImpList A0 }+: IMP_TYPE_SPEC '(' IMP_ELEMENTS ')'+ { ImpList () (getTransSpan $1 $4) $1 $ aReverse $3 }++IMP_ELEMENTS :: { AList ImpElement A0 }+: IMP_ELEMENTS ',' IMP_ELEMENT { setSpan (getTransSpan $1 $3) $ $3 `aCons` $1 }+| IMP_ELEMENT { AList () (getSpan $1) [ $1 ] }++IMP_ELEMENT :: { ImpElement A0 }+: id {% do+ let (TId s id) = $1+ if length id /= 1+ then fail "Implicit argument must be a character."+ else return $ ImpCharacter () s id+ }+| id '-' id {% do+ let (TId _ id1) = $1+ let (TId _ id2) = $3+ if length id1 /= 1 || length id2 /= 1+ then fail "Implicit argument must be a character."+ else return $ ImpRange () (getTransSpan $1 $3) id1 id2+ }++ELEMENT :: { Expression A0 }+: SUBSCRIPT { $1 }++DATA_GROUPS :: { [DataGroup A0] }+: DATA_GROUPS ',' DATA_GROUP { $3 : $1 }+| DATA_GROUPS DATA_GROUP { $2 : $1 }+| DATA_GROUP { [$1] }++DATA_GROUP :: { DataGroup A0 }+: DATA_NAMES '/' DATA_ITEMS '/' { DataGroup () (getTransSpan $1 $4) (aReverse $1) (aReverse $3) }++DATA_NAMES :: { AList Expression A0 }+: NAME_LIST { $1 }+| IMPLIED_DO { fromList () [ $1 ] }++DATA_ITEMS :: { AList Expression A0 }+: DATA_ITEMS ',' DATA_ITEM { setSpan (getTransSpan $1 $3) $ $3 `aCons` $1}+| DATA_ITEM { AList () (getSpan $1) [ $1 ] }++DATA_ITEM :: { Expression A0 }+: INTEGER_CONSTANT '*' DATA_ITEM_LEVEL1 { ExpBinary () (getTransSpan $1 $3) Multiplication $1 $3 }+| DATA_ITEM_LEVEL1 { $1 }++DATA_ITEM_LEVEL1 :: { Expression A0 }+: SIGNED_NUMERIC_LITERAL { $1 }+-- | COMPLEX_LITERAL { $1 }+| VARIABLE { $1 }+| '(' SIGNED_NUMERIC_LITERAL ',' SIGNED_NUMERIC_LITERAL ')' { ExpValue () (getTransSpan $1 $5) (ValComplex $2 $4)}+| LOGICAL_LITERAL { $1 }+| STRING { $1 }+| HOLLERITH { $1 }++EQUIVALENCE_GROUPS :: { AList (AList Expression) A0 }+: EQUIVALENCE_GROUPS ',' '(' NAME_LIST ')' { setSpan (getTransSpan $1 $5) $ (setSpan (getTransSpan $3 $5) $ aReverse $4) `aCons` $1 }+| '(' NAME_LIST ')' { let s = (getTransSpan $1 $3) in AList () s [ setSpan s $ aReverse $2 ] }++POINTER_LIST :: { [ Declarator A0 ] }+: POINTER_LIST ',' POINTER { $3 : $1 }+| POINTER { [ $1 ] }++POINTER :: { Declarator A0 }+: '(' VARIABLE ',' VARIABLE ')'+ { Declarator () (getTransSpan $1 $5) $2 ScalarDecl Nothing (Just $4) }++COMMON_GROUPS :: { AList CommonGroup A0 }+: COMMON_GROUPS COMMON_GROUP { setSpan (getTransSpan $1 $2) $ $2 `aCons` $1 }+| INIT_COMMON_GROUP { AList () (getSpan $1) [ $1 ] }++COMMON_GROUP :: { CommonGroup A0 }+: COMMON_NAME UNINITIALIZED_DECLARATORS { CommonGroup () (getTransSpan $1 $2) (Just $1) $ aReverse $2 }+| '/' '/' UNINITIALIZED_DECLARATORS { CommonGroup () (getTransSpan $1 $3) Nothing $ aReverse $3 }++INIT_COMMON_GROUP :: { CommonGroup A0 }+: COMMON_NAME UNINITIALIZED_DECLARATORS { CommonGroup () (getTransSpan $1 $2) (Just $1) $ aReverse $2 }+| '/' '/' UNINITIALIZED_DECLARATORS { CommonGroup () (getTransSpan $1 $3) Nothing $ aReverse $3 }+| UNINITIALIZED_DECLARATORS { CommonGroup () (getSpan $1) Nothing $ aReverse $1 }++COMMON_NAME :: { Expression A0 }+: '/' VARIABLE '/' { setSpan (getTransSpan $1 $3) $2 }++NAME_LIST :: { AList Expression A0 }+: NAME_LIST ',' ELEMENT+ { setSpan (getTransSpan $1 $3) $ $3 `aCons` $1 }+| ELEMENT { AList () (getSpan $1) [ $1 ] }++UNINITIALIZED_DECLARATORS :: { AList Declarator A0 }+: UNINITIALIZED_DECLARATORS ',' UNINITIALIZED_DECLARATOR { setSpan (getTransSpan $1 $3) $ $3 `aCons` $1 }+| UNINITIALIZED_DECLARATOR { AList () (getSpan $1) [ $1 ] }++UNINITIALIZED_DECLARATOR :: { Declarator A0 }+: UNINITIALIZED_ARRAY_DECLARATOR { $1 }+| UNINITIALIZED_VARIABLE_DECLARATOR { $1 }++UNINITIALIZED_ARRAY_DECLARATOR :: { Declarator A0 }+: VARIABLE '(' DIMENSION_DECLARATORS ')'+ { Declarator () (getTransSpan $1 $4) $1 (ArrayDecl (aReverse $3)) Nothing Nothing }+| VARIABLE '*' SIMPLE_EXPRESSION '(' DIMENSION_DECLARATORS ')'+ { Declarator () (getTransSpan $1 $6) $1 (ArrayDecl (aReverse $5)) (Just $3) Nothing }+| VARIABLE '(' DIMENSION_DECLARATORS ')' '*' SIMPLE_EXPRESSION+ { Declarator () (getTransSpan $1 $6) $1 (ArrayDecl (aReverse $3)) (Just $6) Nothing }++UNINITIALIZED_VARIABLE_DECLARATOR :: { Declarator A0 }+: VARIABLE+ { Declarator () (getSpan $1) $1 ScalarDecl Nothing Nothing }+| VARIABLE '*' SIMPLE_EXPRESSION+ { Declarator () (getTransSpan $1 $3) $1 ScalarDecl (Just $3) Nothing }++INITIALIZED_DECLARATORS :: { AList Declarator A0 }+: INITIALIZED_DECLARATORS ',' INITIALIZED_DECLARATOR { setSpan (getTransSpan $1 $3) $ $3 `aCons` $1 }+| INITIALIZED_DECLARATOR { AList () (getSpan $1) [ $1 ] }++INITIALIZED_DECLARATOR :: { Declarator A0 }+: INITIALIZED_ARRAY_DECLARATOR { $1 }+| INITIALIZED_VARIABLE_DECLARATOR { $1 }++INITIALIZED_ARRAY_DECLARATORS :: { AList Declarator A0 }+: INITIALIZED_ARRAY_DECLARATORS ',' INITIALIZED_ARRAY_DECLARATOR+ { setSpan (getTransSpan $1 $3) $ $3 `aCons` $1 }+| INITIALIZED_ARRAY_DECLARATOR { AList () (getSpan $1) [ $1 ] }++INITIALIZED_ARRAY_DECLARATOR :: { Declarator A0 }+: UNINITIALIZED_ARRAY_DECLARATOR { $1 }+| VARIABLE '(' DIMENSION_DECLARATORS ')' '/' SIMPLE_EXPRESSION_LIST '/'+ { Declarator () (getTransSpan $1 $7) $1 (ArrayDecl (aReverse $3)) Nothing+ (Just (ExpInitialisation () (getSpan $6) (fromReverseList $6))) }+| VARIABLE '*' SIMPLE_EXPRESSION '(' DIMENSION_DECLARATORS ')' '/' SIMPLE_EXPRESSION_LIST '/'+ { Declarator () (getTransSpan $1 $9) $1 (ArrayDecl (aReverse $5)) (Just $3)+ (Just (ExpInitialisation () (getSpan $8) (fromReverseList $8))) }+| VARIABLE '(' DIMENSION_DECLARATORS ')' '*' SIMPLE_EXPRESSION '/' SIMPLE_EXPRESSION_LIST '/'+ { Declarator () (getTransSpan $1 $9) $1 (ArrayDecl (aReverse $3)) (Just $6)+ (Just (ExpInitialisation () (getSpan $8) (fromReverseList $8))) }++INITIALIZED_VARIABLE_DECLARATOR :: { Declarator A0 }+: UNINITIALIZED_VARIABLE_DECLARATOR { $1 }+| VARIABLE '/' SIMPLE_EXPRESSION '/'+ { Declarator () (getTransSpan $1 $4) $1 ScalarDecl Nothing (Just $3) }+| VARIABLE '*' SIMPLE_EXPRESSION '/' SIMPLE_EXPRESSION '/'+ { Declarator () (getTransSpan $1 $6) $1 ScalarDecl (Just $3) (Just $5) }++SIMPLE_EXPRESSION_LIST :: { [Expression A0] }+: SIMPLE_EXPRESSION_LIST ',' SIMPLE_EXPRESSION { $3 : $1 }+| SIMPLE_EXPRESSION { [ $1 ] }++SIMPLE_EXPRESSION :: { Expression A0 }+: INTEGER_CONSTANT '*' CONSTANT { ExpBinary () (getTransSpan $1 $3) Multiplication $1 $3 }+| CONSTANT { $1 }+| '(' '*' ')' { ExpValue () (getSpan $2) ValStar }+| '(' EXPRESSION ')' { $2 }++CONSTANT :: { Expression A0 }+: VARIABLE { $1 }+| SIGNED_NUMERIC_LITERAL { $1 }+| LOGICAL_LITERAL { $1 }+| STRING { $1 }+| HOLLERITH { $1 }++INTEGER_CONSTANT :: { Expression A0 }+: VARIABLE { $1 }+| SIGNED_NUMERIC_LITERAL { $1 }++DIMENSION_DECLARATORS :: { AList DimensionDeclarator A0 }+: DIMENSION_DECLARATORS ',' DIMENSION_DECLARATOR+ { setSpan (getTransSpan $1 $3) $ $3 `aCons` $1 }+| DIMENSION_DECLARATOR { AList () (getSpan $1) [ $1 ] }++DIMENSION_DECLARATOR :: { DimensionDeclarator A0 }+: EXPRESSION ':' EXPRESSION { DimensionDeclarator () (getTransSpan $1 $3) (Just $1) (Just $3) }+| EXPRESSION { DimensionDeclarator () (getSpan $1) Nothing (Just $1) }+| EXPRESSION ':' '*' { DimensionDeclarator () (getTransSpan $1 $3) (Just $1) (Just $ ExpValue () (getSpan $3) ValStar) }+| '*' { DimensionDeclarator () (getSpan $1) Nothing (Just $ ExpValue () (getSpan $1) ValStar) }++-- Here the procedure should be either a function or subroutine name, but+-- since they are syntactically identical at this stage subroutine names+-- are also emitted as function names.+FUNCTION_NAMES :: { AList Expression A0 }+: FUNCTION_NAMES ',' VARIABLE { setSpan (getTransSpan $1 $3) $ $3 `aCons` $1 }+| VARIABLE { AList () (getSpan $1) [ $1 ] }++ARGUMENTS :: { AList Argument A0 }+: ARGUMENTS_LEVEL1 ')' { setSpan (getTransSpan $1 $2) $ aReverse $1 }++ARGUMENTS_LEVEL1 :: { AList Argument A0 }+: ARGUMENTS_LEVEL1 ',' CALLABLE_EXPRESSION { setSpan (getTransSpan $1 $3) $ $3 `aCons` $1 }+| '(' CALLABLE_EXPRESSION { AList () (getTransSpan $1 $2) [ $2 ] }+| '(' { AList () (getSpan $1) [ ] }++-- Expression all by itself subsumes all other callable expressions.+CALLABLE_EXPRESSION :: { Argument A0 }+-- Explicitly parse special intrinsics for argument passing types+: '%' id '(' EXPRESSION ')'+ { let { args = AList () (getSpan $4) $ [Argument () (getSpan $4) Nothing (ArgExpr $4)];+ TId _ name = $2;+ intr = ExpFunctionCall () (getTransSpan $1 $5)+ (ExpValue () (getTransSpan $1 $2) (ValIntrinsic ('%':name)))+ (Just args) }+ in Argument () (getTransSpan $1 $5) Nothing (ArgExpr intr) }+| id '=' EXPRESSION+ { let TId span keyword = $1+ in Argument () (getTransSpan span $3) (Just keyword) (ArgExpr $3) }+| '(' VARIABLE ')'+ { let ExpValue _ _ (ValVariable v) = $2+ in Argument () (getTransSpan $1 $3) Nothing (ArgExprVar () (getSpan $2) v) }+| EXPRESSION { Argument () (getSpan $1) Nothing (ArgExpr $1) }++EXPRESSION :: { Expression A0 }+: EXPRESSION '+' EXPRESSION { ExpBinary () (getTransSpan $1 $3) Addition $1 $3 }+| EXPRESSION '-' EXPRESSION { ExpBinary () (getTransSpan $1 $3) Subtraction $1 $3 }+| EXPRESSION '*' EXPRESSION { ExpBinary () (getTransSpan $1 $3) Multiplication $1 $3 }+| EXPRESSION '/' EXPRESSION { ExpBinary () (getTransSpan $1 $3) Division $1 $3 }+| EXPRESSION '**' EXPRESSION { ExpBinary () (getTransSpan $1 $3) Exponentiation $1 $3 }+| EXPRESSION '/' '/' EXPRESSION %prec CONCAT { ExpBinary () (getTransSpan $1 $4) Concatenation $1 $4 }+| ARITHMETIC_SIGN EXPRESSION %prec NEGATION { ExpUnary () (getTransSpan (fst $1) $2) (snd $1) $2 }+| EXPRESSION or EXPRESSION { ExpBinary () (getTransSpan $1 $3) Or $1 $3 }+| EXPRESSION xor EXPRESSION { ExpBinary () (getTransSpan $1 $3) XOr $1 $3 }+| EXPRESSION and EXPRESSION { ExpBinary () (getTransSpan $1 $3) And $1 $3 }+| not EXPRESSION { ExpUnary () (getTransSpan $1 $2) Not $2 }+| EXPRESSION eqv EXPRESSION { ExpBinary () (getTransSpan $1 $3) Equivalent $1 $3 }+| EXPRESSION neqv EXPRESSION { ExpBinary () (getTransSpan $1 $3) NotEquivalent $1 $3 }+| EXPRESSION RELATIONAL_OPERATOR EXPRESSION %prec RELATIONAL { ExpBinary () (getTransSpan $1 $3) $2 $1 $3 }+| '(' EXPRESSION ')' { setSpan (getTransSpan $1 $3) $2 }+| NUMERIC_LITERAL { $1 }+| '(' EXPRESSION ',' EXPRESSION ')' { ExpValue () (getTransSpan $1 $5) (ValComplex $2 $4) }+| LOGICAL_LITERAL { $1 }+| HOLLERITH { $1 }+-- There should be FUNCTION_CALL here but as far as the parser is concerned it is same as SUBSCRIPT,+-- hence putting it here would cause a reduce/reduce conflict.+| SUBSCRIPT { $1 }+| IMPLIED_DO { $1 }+| '(/' EXPRESSION_LIST '/)' {+ let { exps = reverse $2;+ expList = AList () (getSpan exps) exps }+ in ExpInitialisation () (getTransSpan $1 $3) expList+ }+| '*' INTEGER_LITERAL { ExpReturnSpec () (getTransSpan $1 $2) $2 }+| '&' INTEGER_LITERAL { ExpReturnSpec () (getTransSpan $1 $2) $2 }++IMPLIED_DO :: { Expression A0 }+: '(' EXPRESSION ',' DO_SPECIFICATION ')' {+ let expList = AList () (getSpan $2) [ $2 ]+ in ExpImpliedDo () (getTransSpan $1 $5) expList $4+ }+| '(' EXPRESSION ',' EXPRESSION ',' DO_SPECIFICATION ')' {+ let expList = AList () (getTransSpan $2 $4) [ $2, $4 ]+ in ExpImpliedDo () (getTransSpan $1 $5) expList $6+ }+| '(' EXPRESSION ',' EXPRESSION ',' EXPRESSION_LIST ',' DO_SPECIFICATION ')' {+ let { exps = reverse $6;+ expList = AList () (getTransSpan $2 exps) ($2 : $4 : reverse $6) }+ in ExpImpliedDo () (getTransSpan $1 $9) expList $8+ }++EXPRESSION_LIST :: { [ Expression A0 ] }+: EXPRESSION_LIST ',' EXPRESSION { $3 : $1 }+| EXPRESSION { [ $1 ] }++STRING :: { Expression A0 } : string { let (TString s cs) = $1 in ExpValue () s (ValString cs) }++CONSTANT_EXPRESSION :: { Expression A0 }+: CONSTANT_EXPRESSION '+' CONSTANT_EXPRESSION { ExpBinary () (getTransSpan $1 $3) Addition $1 $3 }+| CONSTANT_EXPRESSION '-' CONSTANT_EXPRESSION { ExpBinary () (getTransSpan $1 $3) Subtraction $1 $3 }+| CONSTANT_EXPRESSION '*' CONSTANT_EXPRESSION { ExpBinary () (getTransSpan $1 $3) Multiplication $1 $3 }+| CONSTANT_EXPRESSION '/' CONSTANT_EXPRESSION { ExpBinary () (getTransSpan $1 $3) Division $1 $3 }+| CONSTANT_EXPRESSION '**' CONSTANT_EXPRESSION { ExpBinary () (getTransSpan $1 $3) Exponentiation $1 $3 }+| CONSTANT_EXPRESSION '/' '/' CONSTANT_EXPRESSION %prec CONCAT { ExpBinary () (getTransSpan $1 $4) Concatenation $1 $4 }+| ARITHMETIC_SIGN CONSTANT_EXPRESSION %prec NEGATION { ExpUnary () (getTransSpan (fst $1) $2) (snd $1) $2 }+| CONSTANT_EXPRESSION or CONSTANT_EXPRESSION { ExpBinary () (getTransSpan $1 $3) Or $1 $3 }+| CONSTANT_EXPRESSION xor CONSTANT_EXPRESSION { ExpBinary () (getTransSpan $1 $3) XOr $1 $3 }+| CONSTANT_EXPRESSION and CONSTANT_EXPRESSION { ExpBinary () (getTransSpan $1 $3) And $1 $3 }+| not CONSTANT_EXPRESSION { ExpUnary () (getTransSpan $1 $2) Not $2 }+| CONSTANT_EXPRESSION RELATIONAL_OPERATOR CONSTANT_EXPRESSION %prec RELATIONAL { ExpBinary () (getTransSpan $1 $3) $2 $1 $3 }+| '(' CONSTANT_EXPRESSION ')' { setSpan (getTransSpan $1 $3) $2 }+| NUMERIC_LITERAL { $1 }+| '(' CONSTANT_EXPRESSION ',' CONSTANT_EXPRESSION ')' { ExpValue () (getTransSpan $1 $5) (ValComplex $2 $4)}+| LOGICAL_LITERAL { $1 }+| SUBSCRIPT { $1 }+| HOLLERITH { $1 }+| '(/' EXPRESSION_LIST '/)' {+ let { exps = reverse $2;+ expList = AList () (getSpan exps) exps }+ in ExpInitialisation () (getTransSpan $1 $3) expList+ }++ARITHMETIC_CONSTANT_EXPRESSION :: { Expression A0 }+: ARITHMETIC_CONSTANT_EXPRESSION '+' ARITHMETIC_CONSTANT_EXPRESSION { ExpBinary () (getTransSpan $1 $3) Addition $1 $3 }+| ARITHMETIC_CONSTANT_EXPRESSION '-' ARITHMETIC_CONSTANT_EXPRESSION { ExpBinary () (getTransSpan $1 $3) Subtraction $1 $3 }+| ARITHMETIC_CONSTANT_EXPRESSION '*' ARITHMETIC_CONSTANT_EXPRESSION { ExpBinary () (getTransSpan $1 $3) Multiplication $1 $3 }+| ARITHMETIC_CONSTANT_EXPRESSION '/' ARITHMETIC_CONSTANT_EXPRESSION { ExpBinary () (getTransSpan $1 $3) Division $1 $3 }+| ARITHMETIC_CONSTANT_EXPRESSION '**' ARITHMETIC_CONSTANT_EXPRESSION { ExpBinary () (getTransSpan $1 $3) Exponentiation $1 $3 }+| ARITHMETIC_SIGN ARITHMETIC_CONSTANT_EXPRESSION %prec NEGATION { ExpUnary () (getTransSpan (fst $1) $2) (snd $1) $2 }+| '(' ARITHMETIC_CONSTANT_EXPRESSION ')' { setSpan (getTransSpan $1 $3) $2 }+| NUMERIC_LITERAL { $1 }+| '(' ARITHMETIC_CONSTANT_EXPRESSION ',' ARITHMETIC_CONSTANT_EXPRESSION ')' { ExpValue () (getTransSpan $1 $5) (ValComplex $2 $4)}+| VARIABLE { $1 }+| SUBSCRIPT { $1 }++RELATIONAL_OPERATOR :: { BinaryOp }+: '==' { EQ }+| '!=' { NE }+| '>' { GT }+| '>=' { GTE }+| '<' { LT }+| '<=' { LTE }++SUBSCRIPT :: { Expression A0 }+: 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 ')'+ { ExpSubscript () (getTransSpan $1 $4) $1 (fromReverseList $3) }+| VARIABLE { $1 }+| STRING { $1 }++INDICIES :: { [ Index A0 ] }+: INDICIES ',' INDEX { $3 : $1 }+| INDEX { [ $1 ] }++INDEX :: { Index A0 }+: RANGE { $1 }+| EXPRESSION { IxSingle () (getSpan $1) Nothing $1 }++RANGE :: { Index A0 }+: ':' { IxRange () (getSpan $1) Nothing Nothing Nothing }+| ':' EXPRESSION { IxRange () (getTransSpan $1 $2) Nothing (Just $2) Nothing }+| EXPRESSION ':' { IxRange () (getTransSpan $1 $2) (Just $1) Nothing Nothing }+| EXPRESSION ':' EXPRESSION+ { IxRange () (getTransSpan $1 $3) (Just $1) (Just $3) Nothing }++ARITHMETIC_SIGN :: { (SrcSpan, UnaryOp) }+: '-' { (getSpan $1, Minus) }+| '+' { (getSpan $1, Plus) }++MAYBE_VARIABLES :: { Maybe (AList Expression A0) }+: VARIABLES { Just $ fromReverseList $1 } | {- EMPTY -} { Nothing }++VARIABLES :: { [ Expression A0 ] }+: VARIABLES ',' VARIABLE_OR_STAR { $3 : $1 }+| VARIABLE_OR_STAR { [ $1 ] }++VARIABLE_OR_STAR :: { Expression A0 }+: VARIABLE { $1 }+| '*' { ExpValue () (getSpan $1) ValStar }+| '&' { ExpValue () (getSpan $1) ValStar }++-- This may also be used to parse a function name, or an array name. Since when+-- are valid options in a production there is no way of differentiating them at+-- this stage.+-- This at least reduces reduce/reduce conflicts.+VARIABLE :: { Expression A0 }+: id { ExpValue () (getSpan $1) $ let (TId _ s) = $1 in ValVariable s }++INTEGER_LITERAL :: { Expression A0 }+: int { ExpValue () (getSpan $1) $ let (TInt _ i) = $1 in ValInteger i Nothing}+| boz { let TBozLiteral s b = $1 in ExpValue () s $ ValBoz b }++REAL_LITERAL :: { Expression A0 }+: int EXPONENT { makeRealLit (Just $1) Nothing Nothing (Just $2) }+| int '.' MAYBE_EXPONENT { makeRealLit (Just $1) (Just $2) Nothing $3 }+| '.' int MAYBE_EXPONENT { makeRealLit Nothing (Just $1) (Just $2) $3 }+| int '.' int MAYBE_EXPONENT { makeRealLit (Just $1) (Just $2) (Just $3) $4 }++MAYBE_EXPONENT :: { Maybe (SrcSpan, String) }+: EXPONENT { Just $1 }+| {-EMPTY-} { Nothing }++EXPONENT :: { (SrcSpan, String) }+: exponent { let (TExponent s exp) = $1 in (s, exp) }++SIGNED_NUMERIC_LITERAL :: { Expression A0 }+: ARITHMETIC_SIGN NUMERIC_LITERAL { ExpUnary () (getTransSpan (fst $1) $2) Minus $2 }+| NUMERIC_LITERAL { $1 }++NUMERIC_LITERAL :: { Expression A0 }+: INTEGER_LITERAL { $1 }+| REAL_LITERAL { $1 }++LOGICAL_LITERAL :: { Expression A0 }+: bool { let TBool s b = $1 in ExpValue () s $ ValLogical b Nothing }++HOLLERITH :: { Expression A0 } : hollerith { ExpValue () (getSpan $1) $ let (THollerith _ h) = $1 in ValHollerith h }++LABELS_IN_STATEMENT :: { AList Expression A0 }+: LABELS_IN_STATEMENT_LEVEL1 ')' { setSpan (getTransSpan $1 $2) $ aReverse $1 }++LABELS_IN_STATEMENT_LEVEL1 :: { AList Expression A0 }+: LABELS_IN_STATEMENT_LEVEL1 ',' LABEL_IN_STATEMENT { setSpan (getTransSpan $1 $3) $ $3 `aCons` $1 }+| '(' LABEL_IN_STATEMENT { AList () (getTransSpan $1 $2) [ $2 ] }++-- Labels that occur in the first 6 columns+LABEL_IN_6COLUMN :: { Expression A0 } : label { ExpValue () (getSpan $1) (let (TLabel _ l) = $1 in ValInteger l Nothing) }++-- Labels that occur in statements+LABEL_IN_STATEMENT :: { Expression A0 } : int { ExpValue () (getSpan $1) (let (TInt _ l) = $1 in ValInteger l Nothing) }++TYPE_SPEC :: { TypeSpec A0 }+: integer KIND_SELECTOR { TypeSpec () (getSpan ($1, $2)) TypeInteger $2 }+| real KIND_SELECTOR { TypeSpec () (getSpan ($1, $2)) TypeReal $2 }+| doublePrecision { TypeSpec () (getSpan $1) TypeDoublePrecision Nothing}+| logical KIND_SELECTOR { TypeSpec () (getSpan ($1, $2)) TypeLogical $2 }+| complex KIND_SELECTOR { TypeSpec () (getSpan ($1, $2)) TypeComplex $2 }+| doubleComplex { TypeSpec () (getSpan $1) TypeDoubleComplex Nothing}+| character CHAR_SELECTOR { TypeSpec () (getSpan ($1, $2)) TypeCharacter $2 }+| byte KIND_SELECTOR { TypeSpec () (getSpan ($1, $2)) TypeByte $2 }+| record '/' NAME '/' { TypeSpec () (getSpan ($1, $4)) (TypeCustom $3) Nothing }++KIND_SELECTOR :: { Maybe (Selector A0) }+: KIND_SELECTOR1 { Just $1 }+| {- EMPTY -} { Nothing }++KIND_SELECTOR1 :: { Selector A0 }+: '*' ARITHMETIC_CONSTANT_EXPRESSION+ { Selector () (getTransSpan $1 $2) Nothing (Just $2) }+| '*' '(' STAR ')' { Selector () (getTransSpan $1 $4) Nothing (Just $3) }++CHAR_SELECTOR :: { Maybe (Selector A0) }+: CHAR_SELECTOR1 { Just $1 }+| {- EMPTY -} { Nothing }++CHAR_SELECTOR1 :: { Selector A0 }+: '*' ARITHMETIC_CONSTANT_EXPRESSION+ { Selector () (getTransSpan $1 $2) (Just $2) Nothing }+| '*' '(' STAR ')'+ { Selector () (getTransSpan $1 $4) (Just $3) Nothing }++IMP_TYPE_SPEC :: { TypeSpec A0 }+: TYPE_SPEC { $1 }++STAR :: { Expression A0 }+STAR : '*' { ExpValue () (getSpan $1) ValStar }
+ src/Language/Fortran/Parser/Fixed/Lexer.x view
@@ -0,0 +1,1126 @@+-- -*- Mode: Haskell -*-+-- vim: ft=haskell+{+{-# LANGUAGE UndecidableInstances #-}++module Language.Fortran.Parser.Fixed.Lexer+ (+ -- * Main interface+ lexer, Token(..), vanillaAlexInput, AlexInput(..), LexAction++ -- * Exposed internals for testing+ , lexN+ , lexemeMatch+ , lexer'+ ) where++import Data.Word (Word8)+import Data.Char (toLower, ord, isDigit)+import Data.List (isPrefixOf)+import Data.Maybe (fromJust, isNothing, isJust)+import Data.Data+import qualified Data.Bits+import qualified Data.ByteString.Char8 as B++import Control.Monad.State++import GHC.Generics++import Language.Fortran.Parser.Monad+import Language.Fortran.Version+import Language.Fortran.Util.FirstParameter+import Language.Fortran.Util.Position+import Language.Fortran.Parser.LexerUtils ( readIntOrBoz )+import Language.Fortran.AST.Boz++}++$digit = 0-9+$bit = 0-1+$octalDigit = 0-7+$hexDigit = [a-f $digit]++$hash = [\#]++@binary = b\'$bit+\' | \'$bit+\'b+@octal = o\'$octalDigit+\' | \'$octalDigit+\'o+@hex = [xz]\'$hexDigit+\' | \'$hexDigit+\'[xz]++$letter = a-z+$alphanumeric = [$letter $digit]+$alphanumericExtended = [$letter $digit \_]+$special = [\ \=\+\-\*\/\(\)\,\.\$]++-- This should really be 6 characters but there are many standard non-compliant+-- programs out there.+@idExtended = $letter $alphanumericExtended{0,9} $alphanumericExtended{0,9} $alphanumericExtended{0,9} $alphanumericExtended?+@id = $letter $alphanumeric{0,5}+@label = $digit{1,5}++@idLegacy = [$letter \_] [$alphanumericExtended \$]*++@datatype = "integer" | "real" | "doubleprecision" | "complex" | "logical"+ -- legacy extensions+ | "byte"++-- Numbers+@integerConst = $digit++@posIntegerConst = [1-9] $digit*+@bozLiteralConst = (@binary|@octal|@hex)++-- For reals+@exponent = [ed] [\+\-]? @integerConst++-- For format items+@repeat = @posIntegerConst?+@width = @posIntegerConst++tokens :-++ <0> [c!\*d] / { commentP } { lexComment }+ "!" / { bangCommentP &&& legacy77P } { lexComment }+ <0> @label / { withinLabelColsP } { addSpanAndMatch TLabel }+ <0> . / { \_ ai _ _ -> atColP 6 ai } { toSC keyword }+ <0> " " ;++ <0> $hash { lexHash }++ <0,st,keyword,iif,assn,doo> \n { resetPar >> toSC 0 >> addSpan TNewline }+ <0,st,keyword,iif,assn,doo> \r ;++ <st,keyword,iif,assn,doo> ";" { resetPar >> toSC keyword >> addSpan TNewline }++ <st> "(" { addSpan TLeftPar }+ <keyword> "(" / { legacy77P } { addSpan TLeftPar }+ <iif> "(" { incPar >> addSpan TLeftPar }+ <st> ")" { addSpan TRightPar }+ <keyword> ")" / { legacy77P } { typeSCChange >> addSpan TRightPar }+ <iif> ")" { maybeToKeyword >> addSpan TRightPar }+ <st,iif> "(/" / { formatExtendedP } { addSpan TLeftArrayPar }+ <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 }++ <keyword> @id / { idP } { toSC st >> addSpanAndMatch TId }+ <keyword> @idExtended / { extendedIdP } { toSC st >> addSpanAndMatch TId }+ <keyword> @idLegacy / { legacyIdP } { toSC st >> addSpanAndMatch TId }++ <keyword> "include" / { extended77P } { toSC st >> addSpan TInclude }++ -- Tokens related to procedures and subprograms+ <keyword> "program" { toSC st >> addSpan TProgram }+ <keyword> "function" / { functionP } { toSC st >> addSpan TFunction }+ <keyword> "subroutine" { toSC st >> addSpan TSubroutine }+ <keyword> "blockdata" { toSC st >> addSpan TBlockData }+ <keyword> "structure" / { legacy77P } { toSC st >> addSpan TStructure }+ <keyword> "union" / { legacy77P } { toSC st >> addSpan TUnion }+ <keyword> "map" / { legacy77P } { toSC st >> addSpan TMap }+ <keyword> "endstructure" / { legacy77P } { toSC st >> addSpan TEndStructure }+ <keyword> "endunion" / { legacy77P } { toSC st >> addSpan TEndUnion }+ <keyword> "endmap" / { legacy77P } { toSC st >> addSpan TEndMap }+ <keyword> "record" / { legacy77P } { toSC st >> addSpan TRecord }+ <keyword> "end" { toSC st >> addSpan TEnd }+ <keyword> "endprogram" / { legacy77P } { toSC st >> addSpan TEndProgram }+ <keyword> "endfunction" / { legacy77P } { toSC st >> addSpan TEndFunction }+ <keyword> "endsubroutine" / { legacy77P } { toSC st >> addSpan TEndSubroutine }++ -- Tokens related to assignment statements+ <keyword> "assign" { toSC assn >> addSpan TAssign }+ <assn> @integerConst { addSpanAndMatch TInt }+ <assn> "to" { addSpan TTo }+ <assn> @id / { notToP } { addSpanAndMatch TId }+ <assn> @idExtended / { notToP &&& extended77P } { addSpanAndMatch TId }+ <assn> @idLegacy / { notToP &&& legacy77P } { addSpanAndMatch TId }+ <st,iif> "=" { addSpan TOpAssign }++ -- Tokens related to control statements+ <keyword> "goto" { toSC st >> addSpan TGoto }+ <keyword> "if" / { ifP } { toSC iif >> addSpan TIf }+ <st,keyword> "then" / { fortran77P } { toSC keyword >> addSpan TThen }+ <keyword> "else" / {fortran77P } { addSpan TElse }+ <keyword> "elseif" / {fortran77P } { toSC st >> addSpan TElsif }+ <keyword> "endif" / {fortran77P } { addSpan TEndif }+ <keyword> "call" { toSC st >> addSpan TCall }+ <keyword> "return" { toSC st >> addSpan TReturn }+ <keyword> "save" / { fortran77P } { toSC st >> addSpan TSave }+ <keyword> "continue" { toSC st >> addSpan TContinue }+ <keyword> "stop" { toSC st >> addSpan TStop }+ <keyword> "exit" / { extended77P } { toSC st >> addSpan TExit }+ <keyword> "cycle" / { legacy77P } { toSC st >> addSpan TCycle }+ <keyword> "case" / { legacy77P } { toSC st >> addSpan TCase }+ <keyword> "casedefault" / { legacy77P } { toSC st >> addSpan TCaseDefault }+ <keyword> "selectcase" / { legacy77P } { toSC st >> addSpan TSelectCase }+ <keyword> "endselect" / { legacy77P } { toSC st >> addSpan TEndSelect }+ <keyword> "pause" { toSC st >> addSpan TPause }+ <keyword> "dowhile" / { extended77P } { toSC st >> addSpan TDoWhile }+ <keyword> "enddo" / { extended77P } { toSC st >> addSpan TEndDo }+ <keyword> "do" { toSC doo >> addSpan TDo }+ <doo> @integerConst { addSpanAndMatch TInt }+ <doo> "while" / { extended77P } { toSC st >> addSpan TWhile }+ <doo> @id { toSC st >> addSpanAndMatch TId }+ <doo> @idExtended / { extended77P } { toSC st >> addSpanAndMatch TId }+ <doo> @idLegacy / { legacy77P } { toSC st >> addSpanAndMatch TId }++ -- Tokens related to I/O statements+ <keyword> "read" { toSC st >> addSpan TRead }+ <keyword> "write" { toSC st >> addSpan TWrite }+ <keyword> "rewind" { toSC st >> addSpan TRewind }+ <keyword> "backspace" { toSC st >> addSpan TBackspace }+ <keyword> "endfile" { toSC st >> addSpan TEndfile }+ <keyword> "inquire" / { fortran77P } { toSC st >> addSpan TInquire }+ <keyword> "open" / { fortran77P } { toSC st >> addSpan TOpen }+ <keyword> "close" / { fortran77P } { toSC st >> addSpan TClose }+ <keyword> "print" / { fortran77P } { toSC st >> addSpan TPrint }+ <keyword> "type" / { legacy77P } { toSC st >> addSpan TTypePrint }++ -- Tokens related to non-executable statements++ -- Tokens related to speification statements+ <keyword> "dimension" { toSC st >> addSpan TDimension }+ <keyword> "common" { toSC st >> addSpan TCommon }+ <keyword> "equivalence" { toSC st >> addSpan TEquivalence }+ <keyword> "external" { toSC st >> addSpan TExternal }+ <keyword> "intrinsic" / { fortran77P } { toSC st >> addSpan TIntrinsic }+ <keyword> @datatype { typeSCChange >> addSpanAndMatch TType }+ <st> @datatype / { implicitStP } { addSpanAndMatch TType }++ <keyword> "doublecomplex" / { extended77P } { typeSCChange >> addSpanAndMatch TType }+ <st> "doublecomplex" / { implicitTypeExtendedP } { addSpanAndMatch TType }+ <keyword> "character" / { fortran77P } { typeSCChange >> addSpanAndMatch TType }+ <st> "character" / { implicitType77P } { addSpanAndMatch TType }+ <keyword> "implicit" / { fortran77P } { toSC st >> addSpan TImplicit }+ <st> "none" / { implicitType77P } { addSpan TNone }+ <keyword> "parameter" / { fortran77P } { toSC st >> addSpan TParameter }+ <keyword> "entry" / { fortran77P } { toSC st >> addSpan TEntry }+ <keyword> "pointer" / { legacy77P } { toSC st >> addSpan TPointer }++ -- 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 }+ <fmt> "(".*")" { toSC st >> exitFormat >> addSpanAndMatch TBlob }++ -- Tokens needed to parse integers, reals, double precision and complex+ -- constants+ <st,iif> @exponent / { exponentP } { addSpanAndMatch TExponent }+ <st,iif> @integerConst { addSpanAndMatch TInt }+ -- can be part (end) of function type declaration+ <keyword> @integerConst { typeSCChange >> addSpanAndMatch TInt }+ <st,iif,keyword> @bozLiteralConst / { legacy77P } { addSpanAndMatch $ \ss s -> TBozLiteral ss (parseBoz s) }++ -- String+ <st,iif> \' / { fortran77P } { strAutomaton '\'' 0 }+ <st,iif> \" / { legacy77P } { strAutomaton '"' 0 }++ -- Logicals+ <st,iif> ".true." { addSpan (\s -> TBool s True) }+ <st,iif> ".false." { addSpan (\s -> TBool s False) }++ -- Arithmetic operators+ <st,iif> "+" { addSpan TOpPlus }+ <st,iif> "-" { addSpan TOpMinus }+ <st,iif> "**" { addSpan TOpExp }+ <st,iif> "*" { addSpan TStar }+ -- can be part of function type declaration+ <keyword> "*" / { legacy77P } { addSpan TStar }+ <st,iif> "/" { addSpan TSlash }+ <st,iif> "&" / { legacy77P } { addSpan TAmpersand }++ -- Logical operators+ <st,iif> ".or." { addSpan TOpOr }+ <st,iif> ".and." { addSpan TOpAnd }+ <st,iif> ".not." { addSpan TOpNot }+ <st,iif> ".xor." / { legacy77P } { addSpan TOpXOr }+ <st,iif> ".eqv." / { fortran77P } { addSpan TOpEquivalent }+ <st,iif> ".neqv." / { fortran77P } { addSpan TOpNotEquivalent }++ -- Relational operators+ <st,iif> "<" / { extended77P } { addSpan TOpLT }+ <st,iif> "<=" / { extended77P } { addSpan TOpLE }+ <st,iif> "==" / { extended77P } { addSpan TOpEQ }+ <st,iif> "/=" / { extended77P } { addSpan TOpNE }+ <st,iif> ">" / { extended77P } { addSpan TOpGT }+ <st,iif> ">=" / { extended77P } { addSpan TOpGE }+ <st,iif> ".lt." { addSpan TOpLT }+ <st,iif> ".le." { addSpan TOpLE }+ <st,iif> ".eq." { addSpan TOpEQ }+ <st,iif> ".ne." { addSpan TOpNE }+ <st,iif> ".gt." { addSpan TOpGT }+ <st,iif> ".ge." { addSpan TOpGE }++ -- ID+ <st,iif> @id { addSpanAndMatch TId }+ <st,iif> @idExtended / { extended77P } { addSpanAndMatch TId }+ <st,iif> @idLegacy / { legacy77P } { addSpanAndMatch TId }++ -- Strings+ <st> @posIntegerConst "h" / { fortran66P } { lexHollerith }+ <st,iif> @posIntegerConst "h" / { hollerithP &&& legacy77P } { lexHollerith }++{++--------------------------------------------------------------------------------+-- Predicated lexer helpers+--------------------------------------------------------------------------------++(&&&) :: (FortranVersion -> AlexInput -> Int -> AlexInput -> Bool)+ -> (FortranVersion -> AlexInput -> Int -> AlexInput -> Bool)+ -> (FortranVersion -> AlexInput -> Int -> AlexInput -> Bool)+f &&& g = \ fv ai1 i ai2 -> f fv ai1 i ai2 && g fv ai1 i ai2++formatExtendedP :: FortranVersion -> AlexInput -> Int -> AlexInput -> Bool+formatExtendedP fv _ _ ai = fv `elem` [Fortran77Extended, Fortran77Legacy] &&+ case xs of+ [ TFormat _, _ ] -> False+ [ TLabel _ _, TFormat _ ] -> False+ _ -> True+ where+ xs = take 2 . reverse . aiPreviousTokensInLine $ ai++implicitType77P :: FortranVersion -> AlexInput -> Int -> AlexInput -> Bool+implicitType77P fv b c d = fortran77P fv b c d && implicitStP fv b c d++implicitTypeExtendedP :: FortranVersion -> AlexInput -> Int -> AlexInput -> Bool+implicitTypeExtendedP fv b c d = extended77P fv b c d && implicitStP fv b c d++implicitStP :: FortranVersion -> AlexInput -> Int -> AlexInput -> Bool+implicitStP _ _ _ ai = checkPreviousTokensInLine f ai+ where+ f (TImplicit _) = True+ f _ = False++extendedIdP :: FortranVersion -> AlexInput -> Int -> AlexInput -> Bool+extendedIdP fv a b ai = fv `elem` [Fortran77Extended, Fortran77Legacy] && idP fv a b ai++legacyIdP :: FortranVersion -> AlexInput -> Int -> AlexInput -> Bool+legacyIdP fv a b ai = fv == Fortran77Legacy && idP fv a b ai++idP :: FortranVersion -> AlexInput -> Int -> AlexInput -> Bool+idP fv ao i ai = not (doP fv ai) && not (ifP fv ao i ai)+ && (equalFollowsP fv ai || rParFollowsP fv ai)++doP :: FortranVersion -> AlexInput -> Bool+doP fv ai = isPrefixOf "do" (reverse . lexemeMatch . aiLexeme $ ai) &&+ case unParse (lexer $ f (0::Integer)) ps of+ ParseOk True _ -> True+ _ -> False+ where+ ps = ParseState+ { psAlexInput = ai { aiStartCode = st}+ , psVersion = fv+ , psFilename = "<unknown>"+ , psParanthesesCount = ParanthesesCount 0 False+ , psContext = [ ConStart ] }+ f 0 t =+ case t of+ TNewline{} -> return False+ TEOF{} -> return False+ TLeftPar{} -> lexer $ f 1+ TComma{} -> return True+ _ -> lexer $ f 0+ f !n t =+ case t of+ TLeftPar{} -> lexer $ f (n+1)+ TRightPar{} -> lexer $ f (n-1)+ _ -> lexer $ f n++ifP :: FortranVersion -> AlexInput -> Int -> AlexInput -> Bool+ifP fv _ _ ai = "if" == (reverse . lexemeMatch . aiLexeme $ ai) &&+ case unParse (lexer $ f) ps of+ ParseOk True _ -> True+ _ -> False+ where+ ps = ParseState+ { psAlexInput = ai { aiStartCode = st}+ , psVersion = fv+ , psFilename = "<unknown>"+ , psParanthesesCount = ParanthesesCount 0 False+ , psContext = [ ConStart ] }+ f t =+ case t of+ -- IF is always followed by (+ TLeftPar{} -> return True+ _ -> return False++functionP :: FortranVersion -> AlexInput -> Int -> AlexInput -> Bool+functionP fv _ _ ai = "function" == (reverse . lexemeMatch . aiLexeme $ ai) &&+ case unParse (lexer $ f) ps of+ ParseOk True _ -> True+ _ -> False+ where+ ps = ParseState+ { psAlexInput = ai { aiStartCode = st}+ , psVersion = fv+ , psFilename = "<unknown>"+ , psParanthesesCount = ParanthesesCount 0 False+ , psContext = [ ConStart ] }+ f t =+ case t of+ -- a function keyword should be followed by the name and a left paren+ TId{} -> lexer f+ TLeftPar{} -> return True+ _ -> return False++hollerithP :: FortranVersion -> AlexInput -> Int -> AlexInput -> Bool+hollerithP _ _ _ ai = isDigit (lookBack 2 ai)++notToP :: FortranVersion -> AlexInput -> Int -> AlexInput -> Bool+notToP _ _ _ ai = not $ "to" `isPrefixOf` (reverse . lexemeMatch . aiLexeme $ ai)++equalFollowsP :: FortranVersion -> AlexInput -> Bool+equalFollowsP fv ai =+ case unParse (lexer $ f False (0::Integer)) ps of+ ParseOk True _ -> True+ _ -> False+ where+ ps = ParseState+ { psAlexInput = ai { aiStartCode = st}+ , psVersion = fv+ , psFilename = "<unknown>"+ , psParanthesesCount = ParanthesesCount 0 False+ , psContext = [ ConStart ] }+ f False 0 t =+ case t of+ TNewline{} -> return False+ TEOF{} -> return False+ TOpAssign{} -> return True+ TLeftPar{} -> lexer $ f True 1+ TDot{} -> lexer $ f False 0+ TId{} -> lexer $ f False 0+ _ -> return False+ f False _ _ = return False+ f True 0 t =+ case t of+ TOpAssign{} -> return True+ TDot{} -> lexer $ f True 0+ TId{} -> lexer $ f True 0+ TLeftPar{} -> lexer $ f True 1+ _ -> return False+ f True n t =+ case t of+ TNewline{} -> return False+ TEOF{} -> return False+ TLeftPar{} -> lexer $ f True (n + 1)+ TRightPar{} -> lexer $ f True (n - 1)+ _ -> lexer $ f True n++rParFollowsP :: FortranVersion -> AlexInput -> Bool+rParFollowsP fv ai =+ case unParse (lexer $ f) ps of+ ParseOk True _ -> True+ _ -> False+ where+ ps = ParseState+ { psAlexInput = ai { aiStartCode = st}+ , psVersion = fv+ , psFilename = "<unknown>"+ , psParanthesesCount = ParanthesesCount 0 False+ , psContext = [ ConStart ] }+ f t =+ case t of+ TRightPar{} -> return True+ _ -> return False++commentP :: FortranVersion -> AlexInput -> Int -> AlexInput -> Bool+commentP _ aiOld _ aiNew = atColP 1 aiOld && _endsWithLine+ where+ _endsWithLine = (posColumn . aiPosition) aiNew /= 1++bangCommentP :: FortranVersion -> AlexInput -> Int -> AlexInput -> Bool+bangCommentP _ _ _ aiNew = _endsWithLine+ where+ _endsWithLine = (posColumn . aiPosition) aiNew /= 1++withinLabelColsP :: FortranVersion -> AlexInput -> Int -> AlexInput -> Bool+withinLabelColsP _ aiOld _ aiNew = getCol aiOld >= 1 && getCol aiNew <= 6+ where+ getCol = posColumn . aiPosition++atColP :: Int -> AlexInput -> Bool+atColP n ai = (posColumn . aiPosition) ai == n++-- This predicate allows to distinguish identifiers and real exponent tokens+-- by looking at previous token. Since exponent can only follow a "." or an+-- integer token. Anything other previous token will prevent matching the input+-- as an exponent token.+exponentP :: FortranVersion -> AlexInput -> Int -> AlexInput -> Bool+exponentP _ _ _ ai =+ case aiPreviousTokensInLine ai of+ -- real*8 d8 is not an exponent+ TInt{} : TStar{} : TType{} : _ -> False+ TInt{} : _ -> True+ TDot{} : _ -> True+ _ -> False++fortran66P :: FortranVersion -> AlexInput -> Int -> AlexInput -> Bool+fortran66P fv _ _ _ = fv == Fortran66++fortran77P :: FortranVersion -> AlexInput -> Int -> AlexInput -> Bool+fortran77P fv _ _ _ = fv == Fortran77 || fv == Fortran77Extended || fv == Fortran77Legacy++extended77P :: FortranVersion -> AlexInput -> Int -> AlexInput -> Bool+extended77P fv _ _ _ = fv == Fortran77Extended || fv == Fortran77Legacy++legacy77P :: FortranVersion -> AlexInput -> Int -> AlexInput -> Bool+legacy77P fv _ _ _ = fv == Fortran77Legacy+++--------------------------------------------------------------------------------+-- Lexer helpers+--------------------------------------------------------------------------------++addSpan :: (SrcSpan -> Token) -> LexAction (Maybe Token)+addSpan cons = do+ s <- getLexemeSpan+ return $ Just $ cons s++addSpanAndMatch :: (SrcSpan -> String -> Token) -> LexAction (Maybe Token)+addSpanAndMatch cons = do+ s <- getLexemeSpan+ m <- getMatch+ return $ Just $ cons s m++getLexeme :: LexAction Lexeme+getLexeme = do+ ai <- getAlex+ return $ aiLexeme ai++putLexeme :: Lexeme -> LexAction ()+putLexeme lexeme = do+ ai <- getAlex+ putAlex $ ai { aiLexeme = lexeme }++resetLexeme :: LexAction ()+resetLexeme = putLexeme initLexeme++getMatch :: LexAction String+getMatch = do+ lexeme <- getLexeme+ return $ (reverse . lexemeMatch) lexeme++putMatch :: String -> LexAction ()+putMatch newMatch = do+ lexeme <- getLexeme+ putLexeme $ lexeme { lexemeMatch = reverse newMatch }++incWhiteSensitiveCharCount :: LexAction ()+incWhiteSensitiveCharCount = do+ ai <- getAlex+ let wsc = aiWhiteSensitiveCharCount ai+ putAlex $ ai { aiWhiteSensitiveCharCount = wsc + 1 }++resetWhiteSensitiveCharCount :: LexAction ()+resetWhiteSensitiveCharCount = do+ ai <- getAlex+ putAlex $ ai { aiWhiteSensitiveCharCount = 0 }++setCaseSensitive :: LexAction ()+setCaseSensitive = do+ ai <- getAlex+ putAlex $ ai { aiCaseSensitive = True }++setCaseInsensitive :: LexAction ()+setCaseInsensitive = do+ ai <- getAlex+ putAlex $ ai { aiCaseSensitive = False }++enterFormat :: LexAction ()+enterFormat = do+ ai <- getAlex+ putAlex $ ai { aiInFormat = True }++exitFormat :: LexAction ()+exitFormat = do+ ai <- getAlex+ putAlex $ ai { aiInFormat = False }++instance Spanned Lexeme where+ getSpan lexeme =+ let ms = lexemeStart lexeme+ me = lexemeEnd lexeme in+ SrcSpan (fromJust ms) (fromJust me)+ setSpan _ = error "Lexeme span cannot be set."++updatePreviousToken :: Maybe Token -> LexAction ()+updatePreviousToken maybeToken = do+ ai <- getAlex+ putAlex $ ai { aiPreviousToken = maybeToken }++addToPreviousTokensInLine :: Token -> LexAction ()+addToPreviousTokensInLine token = do+ ai <- getAlex+ putAlex $+ case token of+ TNewline _ -> updatePrevTokens ai [ ]+ t -> updatePrevTokens ai $ t : aiPreviousTokensInLine ai+ where+ updatePrevTokens ai tokens = ai { aiPreviousTokensInLine = tokens }++checkPreviousTokensInLine :: (Token -> Bool) -> AlexInput -> Bool+checkPreviousTokensInLine prop ai = any prop $ aiPreviousTokensInLine ai++getLexemeSpan :: LexAction SrcSpan+getLexemeSpan = do+ lexeme <- getLexeme+ return $ getSpan lexeme++-- Handle pragmas that begin with #+lexHash :: LexAction (Maybe Token)+lexHash = do+ lexLineWithWhitespace $ \ m -> do+ ai <- getAlex+ case words (drop 1 m) of+ -- 'line' pragma - rewrite the current line and filename+ "line":lineStr:_+ | line <- readIntOrBoz lineStr -> do+ let revdropWNQ = reverse . drop 1 . dropWhile (flip notElem "'\"")+ let file = revdropWNQ . revdropWNQ $ m+ let lineOffs = fromIntegral line - posLine (aiPosition ai) - 1+ let newP = (aiPosition ai) { posPragmaOffset = Just (lineOffs, file)+ , posColumn = 1 }+ putAlex $ ai { aiPosition = newP }+ _ -> return ()+ return Nothing++-- Lex comments with whitespace included+lexComment :: LexAction (Maybe Token)+lexComment =+ lexLineWithWhitespace $ \ m -> do+ s <- getLexemeSpan+ return . Just . TComment s $ tail m++-- Get a line without losing the whitespace, then call continuation with it.+lexLineWithWhitespace :: (String -> LexAction (Maybe Token)) -> LexAction (Maybe Token)+lexLineWithWhitespace k = do+ alex <- getAlex+ let modifiedAlex = alex { aiWhiteSensitiveCharCount = 1 }+ case alexGetByte modifiedAlex of+ Just (w, newAlex)+ | fromIntegral w /= ord '\n' -> putAlex newAlex >> lexLineWithWhitespace k+ _ -> getMatch >>= k+++--------------------------------------------------++{-+ Chars+ +-++ | |+ | |+ | v+ +-+ Nothing +-+++---> |0|---------->+3|+ +-> +++ +-++ | |+' | | '+ | v+ | +++ Nothing +-++ +---|1|----------->2|+ +++ ++++ | ^+ +-------------++ Chars+-}+strAutomaton :: Char -> Int -> LexAction (Maybe Token)+strAutomaton c 0 = do+ setCaseSensitive+ incWhiteSensitiveCharCount+ alex <- getAlex+ case alexGetByte alex of+ Just (_, newAlex) -> do+ putAlex newAlex+ m <- getMatch+ if last m == c+ then strAutomaton c 1+ else strAutomaton c 0+ Nothing -> strAutomaton c 3+strAutomaton c 1 = do+ incWhiteSensitiveCharCount+ alex <- getAlex+ case alexGetByte alex of+ Just (_, newAlex) -> do+ let m = lexemeMatch . aiLexeme $ newAlex+ if head m == c+ then do+ putAlex newAlex+ putMatch $ reverse . tail $ m+ strAutomaton c 0+ else strAutomaton c 2+ Nothing -> strAutomaton c 2+strAutomaton _ 2 = do+ s <- getLexemeSpan+ m <- getMatch+ resetWhiteSensitiveCharCount+ setCaseInsensitive+ return $ Just $ TString s $ (init . tail) m+strAutomaton _ _ = fail "Unmatched string."++lexHollerith :: LexAction (Maybe Token)+lexHollerith = do+ match' <- getMatch+ let len = read $ init match' -- Get n of "nH" from string+ putMatch ""+ ai <- getAlex+ putAlex $ ai { aiWhiteSensitiveCharCount = len }+ lexed <- lexN len+ s <- getLexemeSpan+ return $ do+ hollerith <- lexed+ return $ THollerith s hollerith++lexN :: Int -> LexAction (Maybe String)+lexN n = do+ alex <- getAlex+ match' <- getMatch+ let len = length match'+ if n == len+ then return $ Just match'+ else+ case alexGetByte alex of+ Just (w, _) | fromIntegral w == ord '\n' -> do+ return . Just $! pad match'+ Just (_, newAlex) -> do+ putAlex newAlex+ lexN n+ Nothing -> return Nothing+ where+ pad s = s ++ replicate (n - length s) ' '++maybeToKeyword :: LexAction (Maybe Token)+maybeToKeyword = do+ decPar+ pcActual' <- pcActual . psParanthesesCount <$> get+ if pcActual' == 0+ then toSC keyword+ else return Nothing++typeSCChange :: LexAction (Maybe Token)+typeSCChange = do+ ps <- get+ let hypotheticalPs = ps { psAlexInput = (psAlexInput ps) { aiStartCode = keyword } }+ let isFunction = case unParse (lexer f) hypotheticalPs of { ParseOk True _ -> True; _ -> False }+ if isFunction+ then return Nothing+ else toSC st+ where+ f TFunction{} = return True+ -- can be part of function type declaration+ f TLeftPar{} = lexer f+ f TRightPar{} = lexer f+ f TStar{} = lexer f+ f TInt{} = lexer f+ f _ = return False++toSC :: Int -> LexAction (Maybe Token)+toSC startCode = do+ ai <- getAlex+ if startCode == 0+ then putAlex $ ai { aiStartCode = startCode, aiWhiteSensitiveCharCount = 6 }+ else putAlex $ ai { aiStartCode = startCode }+ return Nothing++--------------------------------------------------------------------------------+-- Tokens+--------------------------------------------------------------------------------++data Token = TLeftPar SrcSpan+ | TRightPar SrcSpan+ | TLeftArrayPar SrcSpan+ | TRightArrayPar SrcSpan+ | TComma SrcSpan+ | TDot SrcSpan+ | TPercent SrcSpan+ | TColon SrcSpan+ | TInclude SrcSpan+ | TProgram SrcSpan+ | TFunction SrcSpan+ | TSubroutine SrcSpan+ | TBlockData SrcSpan+ | TStructure SrcSpan+ | TRecord SrcSpan+ | TUnion SrcSpan+ | TMap SrcSpan+ | TEndProgram SrcSpan+ | TEndFunction SrcSpan+ | TEndSubroutine SrcSpan+ | TEndStructure SrcSpan+ | TEndUnion SrcSpan+ | TEndMap SrcSpan+ | TEnd SrcSpan+ | TAssign SrcSpan+ | TOpAssign SrcSpan+ | TTo SrcSpan+ | TGoto SrcSpan+ | TIf SrcSpan+ | TThen SrcSpan+ | TElse SrcSpan+ | TElsif SrcSpan+ | TEndif SrcSpan+ | TCall SrcSpan+ | TReturn SrcSpan+ | TSave SrcSpan+ | TContinue SrcSpan+ | TStop SrcSpan+ | TCycle SrcSpan+ | TExit SrcSpan+ | TCase SrcSpan+ | TCaseDefault SrcSpan+ | TSelectCase SrcSpan+ | TEndSelect SrcSpan+ | TPause SrcSpan+ | TDo SrcSpan+ | TDoWhile SrcSpan+ | TWhile SrcSpan+ | TEndDo SrcSpan+ | TRead SrcSpan+ | TWrite SrcSpan+ | TRewind SrcSpan+ | TBackspace SrcSpan+ | TEndfile SrcSpan+ | TInquire SrcSpan+ | TOpen SrcSpan+ | TClose SrcSpan+ | TPrint SrcSpan+ | TTypePrint SrcSpan+ | TDimension SrcSpan+ | TCommon SrcSpan+ | TEquivalence SrcSpan+ | TPointer SrcSpan+ | TExternal SrcSpan+ | TIntrinsic SrcSpan+ | TType SrcSpan String+ | TEntry SrcSpan+ | TImplicit SrcSpan+ | TNone SrcSpan+ | TParameter SrcSpan+ | TData SrcSpan+ | TStatic SrcSpan+ | TAutomatic SrcSpan+ | TFormat SrcSpan+ | TBlob SrcSpan String+ | TInt SrcSpan String+ | TBozLiteral SrcSpan Boz+ | TExponent SrcSpan String+ | TBool SrcSpan Bool+ | TOpPlus SrcSpan+ | TOpMinus SrcSpan+ | TOpExp SrcSpan+ | TStar SrcSpan+ | TSlash SrcSpan+ | TAmpersand SrcSpan+ | TOpOr SrcSpan+ | TOpAnd SrcSpan+ | TOpXOr SrcSpan+ | TOpNot SrcSpan+ | TOpEquivalent SrcSpan+ | TOpNotEquivalent SrcSpan+ | TOpLT SrcSpan+ | TOpLE SrcSpan+ | TOpEQ SrcSpan+ | TOpNE SrcSpan+ | TOpGT SrcSpan+ | TOpGE SrcSpan+ | TId SrcSpan String+ | TComment SrcSpan String+ | TString SrcSpan String+ | THollerith SrcSpan String+ | TLabel SrcSpan String+ | TNewline SrcSpan+ | TEOF SrcSpan+ deriving (Show, Eq, Ord, Data, Typeable, Generic)++instance FirstParameter Token SrcSpan+instance FirstParameter Token SrcSpan => Spanned Token where+ getSpan a = getFirstParameter a+ setSpan e a = setFirstParameter e a++instance Tok Token where+ eofToken (TEOF _) = True+ eofToken _ = False++--------------------------------------------------------------------------------+-- AlexInput & related definitions+--------------------------------------------------------------------------------++data Lexeme = Lexeme+ { lexemeMatch :: String+ , lexemeStart :: Maybe Position+ , lexemeEnd :: Maybe Position+ } deriving (Show)++initLexeme :: Lexeme+initLexeme = Lexeme+ { lexemeMatch = ""+ , lexemeStart = Nothing+ , lexemeEnd = Nothing }++data AlexInput = AlexInput+ { aiSourceBytes :: B.ByteString+ , aiEndOffset :: Int+ , aiPosition :: Position+ , aiBytes :: [Word8]+ , aiPreviousChar :: Char+ , aiLexeme :: Lexeme+ , aiWhiteSensitiveCharCount :: Int+ , aiStartCode :: Int+ , aiPreviousToken :: Maybe Token+ , aiPreviousTokensInLine :: [ Token ]+ , aiCaseSensitive :: Bool+ , aiInFormat :: Bool+ , aiFortranVersion :: FortranVersion+ } deriving (Show)++instance Loc AlexInput where+ getPos = aiPosition++instance LastToken AlexInput Token where+ getLastToken = aiPreviousToken++type LexAction a = Parse AlexInput Token a++vanillaAlexInput :: String -> FortranVersion -> B.ByteString -> AlexInput+vanillaAlexInput fn fv bs = AlexInput+ { aiSourceBytes = bs+ , aiEndOffset = B.length bs+ , aiPosition = initPosition { filePath = fn }+ , aiBytes = []+ , aiPreviousChar = '\n'+ , aiLexeme = initLexeme+ , aiWhiteSensitiveCharCount = 6+ , aiStartCode = 0+ , aiPreviousToken = Nothing+ , aiPreviousTokensInLine = [ ]+ , aiCaseSensitive = False+ , aiInFormat = False+ , aiFortranVersion = fv+ }++updateLexeme :: Maybe Char -> Position -> AlexInput -> AlexInput+updateLexeme maybeChar p ai =+ let lexeme = aiLexeme ai+ match = lexemeMatch lexeme+ newMatch =+ case maybeChar of+ Just c -> c : match+ Nothing -> match+ start = lexemeStart lexeme+ -- skipping should not start a new lexeme+ newStart = if isNothing start && isJust maybeChar then Just p else start+ newEnd = Just p in+ ai { aiLexeme = Lexeme newMatch newStart newEnd }++--------------------------------------------------------------------------------+-- Definitions needed for alexScanUser+--------------------------------------------------------------------------------++data Move = Continuation | Char | Newline | NewlineComment | Comment++alexGetByte :: AlexInput -> Maybe (Word8, AlexInput)+alexGetByte ai+ -- The process of reading individual bytes of the character+ | _bytes /= [] = Just (head _bytes, ai { aiBytes = tail _bytes })+ -- When all characters are already read+ | posAbsoluteOffset _position == aiEndOffset ai = Nothing+ -- Skip the continuation line altogether+ | isContinuation ai && _isWhiteInsensitive = skip Continuation ai+ -- Skip the newline before a comment+ | aiFortranVersion ai == Fortran77Legacy && _isWhiteInsensitive+ && isNewlineCommentsFollowedByContinuation ai = skip NewlineComment ai+ -- If we are not parsing a Hollerith skip whitespace+ | _curChar `elem` [ ' ', '\t' ] && _isWhiteInsensitive = skip Char ai+ -- Ignore inline comments+ | aiFortranVersion ai == Fortran77Legacy &&+ _isWhiteInsensitive && not _inFormat && _curChar == '!' = skip Comment ai+ -- Ignore comments after column 72 in fortran77+ | aiFortranVersion ai == Fortran77Legacy && posColumn _position > 72 && _curChar /= '\n'+ = skip Comment ai+ -- Read genuine character and advance. Also covers white sensitivity.+ | otherwise =+ let (_b:_bs) = utf8Encode _curChar in+ Just(_b, updateLexeme (Just _curChar) _position+ ai {+ aiPosition =+ case _curChar of+ '\n' -> advance Newline ai+ _ -> advance Char ai,+ aiBytes = _bs,+ aiPreviousChar = _curChar,+ aiWhiteSensitiveCharCount =+ if _isWhiteInsensitive+ then 0+ else aiWhiteSensitiveCharCount ai - 1+ })+ where+ _curChar = (if aiCaseSensitive ai then id else toLower) $ currentChar ai+ _bytes = aiBytes ai+ _position = aiPosition ai+ _isWhiteInsensitive = aiWhiteSensitiveCharCount ai == 0+ _inFormat = aiInFormat ai++alexInputPrevChar :: AlexInput -> Char+alexInputPrevChar ai = aiPreviousChar ai++takeNChars :: Integer -> AlexInput -> String+takeNChars n ai =+ B.unpack . B.take (fromIntegral n) . B.drop (fromIntegral _dropN) $ aiSourceBytes ai+ where+ _dropN = posAbsoluteOffset . aiPosition $ ai++currentChar :: AlexInput -> Char+currentChar ai = B.index (aiSourceBytes ai) (fromIntegral . posAbsoluteOffset . aiPosition $ ai)++lookBack :: Int -> AlexInput -> Char+lookBack n ai = B.index (aiSourceBytes ai) (fromIntegral . subtract n . posAbsoluteOffset . aiPosition $ ai)++isContinuation :: AlexInput -> Bool+isContinuation ai =+ take 6 _next7 == "\n " && not (last _next7 `elem` [' ', '0', '\n', '\r'])+ where+ _next7 = takeNChars 7 ai++isNewlineComment :: AlexInput -> Bool+isNewlineComment ai =+ _next1 == "\n" && isCommentLine ai p+ where+ _next1 = takeNChars 1 ai+ p = (aiPosition ai) { posAbsoluteOffset = posAbsoluteOffset (aiPosition ai) + 1 }++isNewlineCommentsFollowedByContinuation :: AlexInput -> Bool+isNewlineCommentsFollowedByContinuation ai+ | isNewlineComment ai+ = isNewlineCommentsFollowedByContinuation (ai { aiPosition = advance NewlineComment ai })+ | isContinuation ai = True+ | otherwise = False++skip :: Move -> AlexInput -> Maybe (Word8, AlexInput)+skip move ai =+ let _newPosition = advance move ai in+ alexGetByte $ updateLexeme Nothing _newPosition $ ai { aiPosition = _newPosition }++advance :: Move -> AlexInput -> Position+advance move ai =+ case move of+ Char ->+ position { posAbsoluteOffset = _absl + 1, posColumn = _col + 1 }+ Continuation ->+ position { posAbsoluteOffset = _absl + 7, posColumn = 7, posLine = _line + 1 }+ Newline ->+ position { posAbsoluteOffset = _absl + 1, posColumn = 1, posLine = _line + 1 }+ NewlineComment ->+ skipComment ai+ position { posAbsoluteOffset = _absl + 1, posColumn = 1, posLine = _line + 1 }+ Comment ->+ skipComment ai position+ where+ position = aiPosition ai+ _col = posColumn position+ _line = posLine position+ _absl = posAbsoluteOffset position++skipComment :: AlexInput -> Position -> Position+skipComment ai p =+ p { posAbsoluteOffset = posAbsoluteOffset p + length line+ , posColumn = posColumn p + length line+ }+ where+ line = takeLine p ai++skipCommentLines :: AlexInput -> Position -> Position+skipCommentLines ai p = go p p+ where+ go p' p''+ -- eof is not a comment line+ | not (null line)+ , isCommentLine ai p''+ = go p'' p''{ posAbsoluteOffset = posAbsoluteOffset p'' + length line + 1 -- skip the newline+ , posColumn = 1, posLine = posLine p'' + 1+ }+ | isContinuation ai'+ = advance Continuation ai'+ | otherwise+ -- after skipping comment lines, place cursor right at the last newline+ = p2+ where+ line = takeLine p'' ai+ line' = takeLine p' ai+ p2 = p' { posAbsoluteOffset = posAbsoluteOffset p' + length line'+ , posColumn = length line' + 1+ }+ ai' = ai { aiPosition = p2 }++isCommentLine :: AlexInput -> Position -> Bool+isCommentLine ai p+ -- eof is not a comment line+ | posAbsoluteOffset p == aiEndOffset ai+ = False+ | map toLower (take 1 line) `elem` ["c", "d", "!", "*"]+ || all (`elem` " \t") line+ || head (dropWhile (`elem` " \t") line) == '!'+ = True+ | otherwise+ = False+ where+ line = takeLine p ai++takeLine :: Position -> AlexInput -> String+takeLine p ai =+ B.unpack . B.takeWhile (/='\n') . B.drop (fromIntegral _dropN) $ aiSourceBytes ai+ where+ _dropN = posAbsoluteOffset p++utf8Encode :: Char -> [Word8]+utf8Encode = map fromIntegral . _go . ord+ where+ _go oc+ | oc <= 0x7f = [oc]+ | oc <= 0x7ff = [ 0xc0 + (oc `Data.Bits.shiftR` 6)+ , 0x80 + oc Data.Bits..&. 0x3f+ ]+ | oc <= 0xffff = [ 0xe0 + (oc `Data.Bits.shiftR` 12)+ , 0x80 + ((oc `Data.Bits.shiftR` 6) Data.Bits..&. 0x3f)+ , 0x80 + oc Data.Bits..&. 0x3f+ ]+ | otherwise = [ 0xf0 + (oc `Data.Bits.shiftR` 18)+ , 0x80 + ((oc `Data.Bits.shiftR` 12) Data.Bits..&. 0x3f)+ , 0x80 + ((oc `Data.Bits.shiftR` 6) Data.Bits..&. 0x3f)+ , 0x80 + oc Data.Bits..&. 0x3f+ ]++--------------------------------------------------------------------------------+-- Lexer definition+--------------------------------------------------------------------------------++lexer :: (Token -> LexAction a) -> LexAction a+lexer cont = cont =<< lexer'++lexer' :: LexAction Token+lexer' = do+ resetLexeme+ alexInput <- getAlex+ let startCode = aiStartCode alexInput+ version <- getVersion+ case alexScanUser version alexInput startCode of+ AlexEOF -> return $ TEOF $ SrcSpan (getPos alexInput) (getPos alexInput)+ AlexError _ -> do+ parseState <- get+ fail $ psFilename parseState ++ ": lexing failed. "+ AlexSkip newAlex _ -> putAlex newAlex >> lexer'+ AlexToken newAlex _ action -> do+ putAlex newAlex+ maybeToken <- action+ case maybeToken of+ Just token -> do+ updatePreviousToken maybeToken+ addToPreviousTokensInLine token+ return token+ Nothing -> lexer'++alexScanUser :: FortranVersion -> AlexInput -> Int -> AlexReturn (LexAction (Maybe Token))++}
+ src/Language/Fortran/Parser/Fixed/Utils.hs view
@@ -0,0 +1,42 @@+{-# LANGUAGE CPP #-}+module Language.Fortran.Parser.Fixed.Utils where++import Language.Fortran.Parser.Fixed.Lexer+import Language.Fortran.AST+import Language.Fortran.AST.RealLit+import Language.Fortran.Util.Position+import Language.Fortran.Parser.Monad+import Control.Monad.State++-- | UNSAFE. Must be called with expected token types (see usage sites). Will+-- cause a runtime exception if it doesn't form a valid REAL literal.+makeRealLit+ :: Maybe Token -> Maybe Token -> Maybe Token -> Maybe (SrcSpan, String)+ -> Expression A0+makeRealLit i1 dot i2 expr =+ let span1 = getSpan (i1, dot, i2)+ span2 = case expr of+ Just e -> getTransSpan span1 (fst e)+ Nothing -> span1+ i1Str = case i1 of { Just (TInt _ s) -> s ; _ -> "" }+ dotStr = case dot of { Just (TDot _) -> "." ; _ -> "" }+ i2Str = case i2 of { Just (TInt _ s) -> s ; _ -> "" }+ exprStr = case expr of { Just (_, s) -> s ; _ -> "" }+ litStr = i1Str ++ dotStr ++ i2Str ++ exprStr+ in ExpValue () span2 $ ValReal (parseRealLit litStr) Nothing++parseError :: Token -> LexAction a+parseError _ = do+ parseState <- get+#ifdef DEBUG+ tokens <- reverse <$> aiPreviousTokensInLine <$> getAlex+#endif+ fail $ psFilename parseState ++ ": parsing failed. "+#ifdef DEBUG+ ++ '\n' : show tokens+#endif++convCmts :: [Block a] -> [ProgramUnit a]+convCmts = map convCmt+ where convCmt (BlComment a s c) = PUComment a s c+ convCmt _ = error "convCmt applied to something that is not a comment"
− src/Language/Fortran/Parser/Fortran2003.y
@@ -1,1477 +0,0 @@--- -*- Mode: Haskell -*---- vim: ft=haskell-{--- Incomplete work-in-progress.-module Language.Fortran.Parser.Fortran2003 ( functionParser- , statementParser- , blockParser- , fortran2003Parser- , fortran2003ParserWithTransforms- , fortran2003ParserWithModFiles- , fortran2003ParserWithModFilesWithTransforms- ) where--import Prelude hiding (EQ,LT,GT) -- Same constructors exist in the AST-import Control.Monad.State-import Data.Maybe (fromMaybe, isJust)-import Data.List (nub)-import Data.Either (either, lefts, rights, partitionEithers)-import Control.Applicative-import qualified Data.ByteString.Char8 as B--#ifdef DEBUG-import Data.Data (toConstr)-#endif--import Language.Fortran.Util.Position-import Language.Fortran.Util.ModFile-import Language.Fortran.ParserMonad-import Language.Fortran.Lexer.FreeForm-import Language.Fortran.AST-import Language.Fortran.Transformer--import Debug.Trace--}--%name programParser PROGRAM-%name functionParser SUBPROGRAM_UNIT-%name blockParser BLOCK-%name statementParser STATEMENT-%monad { LexAction }-%lexer { lexer } { TEOF _ }-%tokentype { Token }-%error { parseError }--%token- id { TId _ _ }- comment { TComment _ _ }- string { TString _ _ }- int { TIntegerLiteral _ _ }- float { TRealLiteral _ _ }- boz { TBozLiteral _ _ }- '_' { TUnderscore _ }- ',' { TComma _ }- ',2' { TComma2 _ }- ';' { TSemiColon _ }- ':' { TColon _ }- '::' { TDoubleColon _ }- '=' { TOpAssign _ }- '=>' { TArrow _ }- '%' { TPercent _ }- '(' { TLeftPar _ }- '(2' { TLeftPar2 _ }- ')' { TRightPar _ }- '(/' { TLeftInitPar _ }- '/)' { TRightInitPar _ }- opCustom { TOpCustom _ _ }- '**' { TOpExp _ }- '+' { TOpPlus _ }- '-' { TOpMinus _ }- '*' { TStar _ }- '/' { TOpDivision _ }- slash { TSlash _ }- or { TOpOr _ }- and { TOpAnd _ }- not { TOpNot _ }- eqv { TOpEquivalent _ }- neqv { TOpNotEquivalent _ }- '<' { TOpLT _ }- '<=' { TOpLE _ }- '==' { TOpEQ _ }- '!=' { TOpNE _ }- '>' { TOpGT _ }- '>=' { TOpGE _ }- bool { TLogicalLiteral _ _ }- program { TProgram _ }- endProgram { TEndProgram _ }- function { TFunction _ }- endFunction { TEndFunction _ }- result { TResult _ }- pure { TPure _ }- elemental { TElemental _ }- recursive { TRecursive _ }- subroutine { TSubroutine _ }- endSubroutine { TEndSubroutine _ }- blockData { TBlockData _ }- endBlockData { TEndBlockData _ }- module { TModule _ }- endModule { TEndModule _ }- contains { TContains _ }- use { TUse _ }- only { TOnly _ }- import { TImport _ }- abstract { TAbstract _ }- interface { TInterface _ }- endInterface { TEndInterface _ }- moduleProcedure { TModuleProcedure _ }- procedure { TProcedure _ }- assignment { TAssignment _ }- operator { TOperator _ }- call { TCall _ }- return { TReturn _ }- entry { TEntry _ }- include { TInclude _ }- public { TPublic _ }- private { TPrivate _ }- protected { TProtected _ }- parameter { TParameter _ }- allocatable { TAllocatable _ }- asynchronous { TAsynchronous _ }- dimension { TDimension _ }- external { TExternal _ }- intent { TIntent _ }- intrinsic { TIntrinsic _ }- nonintrinsic { TNonIntrinsic _ }- optional { TOptional _ }- pointer { TPointer _ }- save { TSave _ }- target { TTarget _ }- value { TValue _ }- volatile { TVolatile _ }- bind { TBind _ }- 'c' { TC _ }- name { TName _ }- in { TIn _ }- out { TOut _ }- inout { TInOut _ }- data { TData _ }- namelist { TNamelist _ }- implicit { TImplicit _ }- equivalence { TEquivalence _ }- common { TCommon _ }- allocate { TAllocate _ }- deallocate { TDeallocate _ }- stat { TStat _ }- errmsg { TErrMsg _ }- source { TSource _ }- nullify { TNullify _ }- none { TNone _ }- goto { TGoto _ }- to { TTo _ }- continue { TContinue _ }- stop { TStop _ }- do { TDo _ }- enddo { TEndDo _ }- while { TWhile _ }- if { TIf _ }- then { TThen _ }- else { TElse _ }- elsif { TElsif _ }- endif { TEndIf _ }- case { TCase _ }- selectcase { TSelectCase _ }- endselect { TEndSelect _ }- associate { TAssociate _ }- endassociate { TEndAssociate _ }- default { TDefault _ }- cycle { TCycle _ }- exit { TExit _ }- where { TWhere _ }- elsewhere { TElsewhere _ }- endwhere { TEndWhere _ }- type { TType _ }- endType { TEndType _ }- class { TClass _ }- enum { TEnum _ }- enumerator { TEnumerator _ }- endEnum { TEndEnum _ }- sequence { TSequence _ }- kind { TKind _ }- len { TLen _ }- integer { TInteger _ }- real { TReal _ }- doublePrecision { TDoublePrecision _ }- logical { TLogical _ }- character { TCharacter _ }- complex { TComplex _ }- open { TOpen _ }- close { TClose _ }- read { TRead _ }- write { TWrite _ }- print { TPrint _ }- flush { TFlush _ }- unit { TUnit _ }- iostat { TIOStat _ }- iomsg { TIOMsg _ }- err { TErr _ }- backspace { TBackspace _ }- rewind { TRewind _ }- inquire { TInquire _ }- endfile { TEndfile _ }- format { TFormat _ }- blob { TBlob _ _ }- end { TEnd _ }- newline { TNewline _ }- forall { TForall _ }- endforall { TEndForall _ }--- Precedence of operators---- Level 6-%left opCustom---- Level 5-%left eqv neqv-%left or-%left and-%right not---- Level 4-%nonassoc '==' '!=' '>' '<' '>=' '<='-%nonassoc RELATIONAL---- Level 3-%left CONCAT---- Level 2-%left '+' '-'-%left '*' '/'-%right SIGN-%right '**'---- Level 1-%right DEFINED_UNARY---- Level 0-%left '%'--%%--maybe(p)-: p { Just $1 }-| {- empty -} { Nothing }---- This rule is to ignore leading whitespace-PROGRAM :: { ProgramFile A0 }-: NEWLINE PROGRAM_INNER { $2 }-| PROGRAM_INNER { $1 }--PROGRAM_INNER :: { ProgramFile A0 }-: PROGRAM_UNITS { ProgramFile (MetaInfo { miVersion = Fortran2003, miFilename = "" }) (reverse $1) }-| {- empty -} { ProgramFile (MetaInfo { miVersion = Fortran2003, miFilename = "" }) [] }--PROGRAM_UNITS :: { [ ProgramUnit A0 ] }-: PROGRAM_UNITS PROGRAM_UNIT MAYBE_NEWLINE { $2 : $1 }-| PROGRAM_UNIT MAYBE_NEWLINE { [ $1 ] }--PROGRAM_UNIT :: { ProgramUnit A0 }-: program NAME NEWLINE BLOCKS MAYBE_SUBPROGRAM_UNITS PROGRAM_END- {% do { unitNameCheck $6 $2;- return $ PUMain () (getTransSpan $1 $6) (Just $2) (reverse $4) $5 } }-| module NAME NEWLINE BLOCKS MAYBE_SUBPROGRAM_UNITS MODULE_END- {% do { unitNameCheck $6 $2;- return $ PUModule () (getTransSpan $1 $6) $2 (reverse $4) $5 } }-| blockData NEWLINE BLOCKS BLOCK_DATA_END- { PUBlockData () (getTransSpan $1 $4) Nothing (reverse $3) }-| blockData NAME NEWLINE BLOCKS BLOCK_DATA_END- {% do { unitNameCheck $5 $2;- return $ PUBlockData () (getTransSpan $1 $5) (Just $2) (reverse $4) } }-| SUBPROGRAM_UNIT { $1 }--MAYBE_SUBPROGRAM_UNITS :: { Maybe [ ProgramUnit A0 ] }-: contains NEWLINE SUBPROGRAM_UNITS { Just $ reverse $3 }-| {- Empty -} { Nothing }--SUBPROGRAM_UNITS :: { [ ProgramUnit A0 ] }-: SUBPROGRAM_UNITS SUBPROGRAM_UNIT NEWLINE { $2 : $1 }-| {- EMPTY -} { [ ] }--SUBPROGRAM_UNIT :: { ProgramUnit A0 }-: PREFIXES function NAME MAYBE_ARGUMENTS FUNC_SUFFIX MAYBE_COMMENT NEWLINE BLOCKS MAYBE_SUBPROGRAM_UNITS FUNCTION_END- {% do { unitNameCheck $10 $3;- let (pfxs, typeSpec) = case partitionEithers $1 of- { (ps, t:_) -> (fromReverseList' ps, Just t)- ; (ps, []) -> (fromReverseList' ps, Nothing) } in- let (sfx, result) = $5 in- let sfx' = fmap (\ s -> AList () (getSpan s) [s]) sfx in- let ss = if null $1 then getTransSpan $2 $10 else getTransSpan (reverse $1) $10 in- if validPrefixSuffix (pfxs, sfx') then- return $ PUFunction () ss typeSpec (pfxs, sfx') $3 $4 result (reverse $8) $9- else fail "Cannot specify elemental along with recursive and/or bind." } }-| PREFIXES subroutine NAME MAYBE_ARGUMENTS SUBR_SUFFIX MAYBE_COMMENT NEWLINE BLOCKS MAYBE_SUBPROGRAM_UNITS SUBROUTINE_END- {% do { unitNameCheck $10 $3;- (pfxs, typeSpec) <- case partitionEithers $1 of- { (ps, t:_) -> fail "Subroutines cannot have return types."- ; (ps, []) -> return (fromReverseList' ps, Nothing) };- let sfx' = fmap (\ s -> AList () (getSpan s) [s]) $5 in- let ss = if null $1 then getTransSpan $2 $10 else getTransSpan (reverse $1) $10 in- if validPrefixSuffix (pfxs, sfx') then- return $ PUSubroutine () ss (pfxs, sfx') $3 $4 (reverse $8) $9- else fail "Cannot specify elemental along with recursive and/or bind." } }-| comment { let (TComment s c) = $1 in PUComment () s (Comment c) }---- (Fortran2003) R1227, Fortran95 (...)-PREFIXES :: { [Either (Prefix A0) (TypeSpec A0)] }-: PREFIXES PREFIX { $2:$1 }-| {- EMPTY -} { [] }---- (Fortran2003) R1228, Fortran95 (...)-PREFIX :: { Either (Prefix A0) (TypeSpec A0) }-: recursive { Left $ PfxRecursive () (getSpan $1) }-| elemental { Left $ PfxElemental () (getSpan $1) }-| pure { Left $ PfxPure () (getSpan $1) }-| TYPE_SPEC { Right $1 }--FUNC_SUFFIX :: { (Maybe (Suffix A0), Maybe (Expression A0)) }-: SUFFIX RESULT { (Just $1, Just $2) }-| RESULT SUFFIX { (Just $2, Just $1) }-| SUFFIX { (Just $1, Nothing) }-| RESULT { (Nothing, Just $1) }-| {- empty -} { (Nothing, Nothing) }--SUBR_SUFFIX :: { Maybe (Suffix A0) }-: SUFFIX { Just $1 }-| {- empty -} { Nothing }---- (Fortran2003) R1229-SUFFIX :: { Suffix A0 }--- (Fortran2003) R509-: bind '(' 'c' ',' name '=' EXPRESSION ')' { SfxBind () (getTransSpan $1 $8) (Just $7) }-| bind '(' 'c' ')' { SfxBind () (getTransSpan $1 $4) Nothing }--MAYBE_ARGUMENTS :: { Maybe (AList Expression A0) }-: '(' MAYBE_VARIABLES ')' { $2 }-| {- Nothing -} { Nothing }--RESULT :: { Expression A0 }-: result '(' VARIABLE ')' { $3 }--MAYBE_RESULT :: { Maybe (Expression A0) }-: RESULT { Just $1 }-| {- empty -} { Nothing}--PROGRAM_END :: { Token }-: end { $1 } | endProgram { $1 } | endProgram id { $2 }-MODULE_END :: { Token }-: end { $1 } | endModule { $1 } | endModule id { $2 }-FUNCTION_END :: { Token }-: end { $1 } | endFunction { $1 } | endFunction id { $2 }-SUBROUTINE_END :: { Token }-: end { $1 } | endSubroutine { $1 } | endSubroutine id { $2 }-BLOCK_DATA_END :: { Token }-: end { $1 } | endBlockData { $1 } | endBlockData id { $2 }-INTERFACE_END :: { Token }-: end { $1 } | endInterface { $1 } | endInterface id { $2 }--NAME :: { Name } : id { let (TId _ name) = $1 in name }--IMPORT_NAME_LIST :: { [Expression A0] }-: IMPORT_NAME_LIST ',' VARIABLE { $3 : $1 }-| VARIABLE { [ $1 ] }--BLOCKS :: { [ Block A0 ] } : BLOCKS BLOCK { $2 : $1 } | {- EMPTY -} { [ ] }--BLOCK :: { Block A0 }-: IF_BLOCK MAYBE_COMMENT NEWLINE { $1 }-| CASE_BLOCK MAYBE_COMMENT NEWLINE { $1 }-| ASSOCIATE_BLOCK MAYBE_COMMENT NEWLINE { $1 }-| INTEGER_LITERAL STATEMENT MAYBE_COMMENT NEWLINE- { BlStatement () (getTransSpan $1 $2) (Just $1) $2 }-| STATEMENT MAYBE_COMMENT NEWLINE { BlStatement () (getSpan $1) Nothing $1 }-| ABSTRACTP interface MAYBE_EXPRESSION MAYBE_COMMENT NEWLINE SUBPROGRAM_UNITS2 MODULE_PROCEDURES INTERFACE_END MAYBE_COMMENT NEWLINE- { BlInterface () (getTransSpan $2 $10) $3 $1 (reverse $6) (reverse $7) }-| ABSTRACTP interface MAYBE_EXPRESSION MAYBE_COMMENT NEWLINE MODULE_PROCEDURES INTERFACE_END MAYBE_COMMENT NEWLINE- { BlInterface () (getTransSpan $2 $9) $3 $1 [ ] (reverse $6) }-| COMMENT_BLOCK { $1 }--IF_BLOCK :: { Block A0 }-: if '(' EXPRESSION ')' then MAYBE_COMMENT NEWLINE BLOCKS ELSE_BLOCKS- { let { startSpan = getSpan $1;- (endSpan, conds, blocks, endLabel) = $9;- span = getTransSpan startSpan endSpan }- in BlIf () span Nothing Nothing ((Just $3):conds) ((reverse $8):blocks) endLabel }-| id ':' if '(' EXPRESSION ')' then MAYBE_COMMENT NEWLINE BLOCKS ELSE_BLOCKS- { let { TId startSpan startName = $1;- (endSpan, conds, blocks, endLabel) = $11;- span = getTransSpan startSpan endSpan }- in BlIf () span Nothing (Just startName) ((Just $5):conds) ((reverse $10):blocks) endLabel }-| INTEGER_LITERAL if '(' EXPRESSION ')' then MAYBE_COMMENT NEWLINE BLOCKS ELSE_BLOCKS- { let { startSpan = getSpan $1;- startLabel = Just $1;- (endSpan, conds, blocks, endLabel) = $10;- span = getTransSpan startSpan endSpan }- in BlIf () span startLabel Nothing ((Just $4):conds) ((reverse $9):blocks) endLabel }-| INTEGER_LITERAL id ':' if '(' EXPRESSION ')' then MAYBE_COMMENT NEWLINE BLOCKS ELSE_BLOCKS- { let { startSpan = getSpan $1;- startLabel = Just $1;- TId _ startName = $2;- (endSpan, conds, blocks, endLabel) = $12;- span = getTransSpan startSpan endSpan }- in BlIf () span startLabel (Just startName) ((Just $6):conds) ((reverse $11):blocks) endLabel }--ELSE_BLOCKS :: { (SrcSpan, [Maybe (Expression A0)], [[Block A0]], Maybe (Expression A0)) }-: maybe(INTEGER_LITERAL) elsif '(' EXPRESSION ')' then MAYBE_COMMENT NEWLINE BLOCKS ELSE_BLOCKS- { let (endSpan, conds, blocks, endLabel) = $10- in (endSpan, Just $4 : conds, reverse $9 : blocks, endLabel) }-| maybe(INTEGER_LITERAL) else MAYBE_COMMENT NEWLINE BLOCKS END_IF- { let (endSpan, endLabel) = $6- in (endSpan, [Nothing], [reverse $5], endLabel) }-| END_IF { let (endSpan, endLabel) = $1 in (endSpan, [], [], endLabel) }--END_IF :: { (SrcSpan, Maybe (Expression A0)) }-: endif { (getSpan $1, Nothing) }-| endif id { (getSpan $2, Nothing) }-| INTEGER_LITERAL endif { (getSpan $2, Just $1) }-| INTEGER_LITERAL endif id { (getSpan $3, Just $1) }--CASE_BLOCK :: { Block A0 }-: selectcase '(' EXPRESSION ')' MAYBE_COMMENT NEWLINE CASES- { let { (caseRanges, blocks, endLabel, endSpan) = $7;- span = getTransSpan $1 endSpan }- in BlCase () span Nothing Nothing $3 caseRanges blocks endLabel }-| INTEGER_LITERAL selectcase '(' EXPRESSION ')' MAYBE_COMMENT NEWLINE CASES- { let { (caseRanges, blocks, endLabel, endSpan) = $8;- span = getTransSpan $1 endSpan }- in BlCase () span (Just $1) Nothing $4 caseRanges blocks endLabel }-| id ':' selectcase '(' EXPRESSION ')' MAYBE_COMMENT NEWLINE CASES- { let { (caseRanges, blocks, endLabel, endSpan) = $9;- TId s startName = $1;- span = getTransSpan s endSpan }- in BlCase () span Nothing (Just startName) $5 caseRanges blocks endLabel }-| INTEGER_LITERAL id ':' selectcase '(' EXPRESSION ')' MAYBE_COMMENT NEWLINE CASES- { let { (caseRanges, blocks, endLabel, endSpan) = $10;- TId s startName = $2;- span = getTransSpan s endSpan }- in BlCase () span (Just $1) (Just startName) $6 caseRanges blocks endLabel }---- We store line comments as statements, but this raises an issue: we have--- nowhere to place comments after a SELECT CASE but before a CASE. So we drop--- them. The inner CASES_ rule does /not/ use this, because comments can always--- be parsed as belonging to to the above CASE block.-CASES :: { ([Maybe (AList Index A0)], [[Block A0]], Maybe (Expression A0), SrcSpan) }-: COMMENT_BLOCK CASES_ { $2 }-| CASES_ { $1 }--CASES_ :: { ([Maybe (AList Index A0)], [[Block A0]], Maybe (Expression A0), SrcSpan) }-: maybe(INTEGER_LITERAL) case '(' INDICIES ')' MAYBE_COMMENT NEWLINE BLOCKS CASES_- { let (scrutinees, blocks, endLabel, endSpan) = $9- in (Just (fromReverseList $4) : scrutinees, reverse $8 : blocks, endLabel, endSpan) }-| maybe(INTEGER_LITERAL) case default MAYBE_COMMENT NEWLINE BLOCKS END_SELECT- { let (endLabel, endSpan) = $7- in ([Nothing], [$6], endLabel, endSpan) }-| END_SELECT- { let (endLabel, endSpan) = $1- in ([], [], endLabel, endSpan) }--END_SELECT :: { (Maybe (Expression A0), SrcSpan) }-: maybe(INTEGER_LITERAL) endselect maybe(id)- { ($1, maybe (getSpan $2) getSpan $3) }--ASSOCIATE_BLOCK :: { Block A0 }-: INTEGER_LITERAL id ':' associate '(' ABBREVIATIONS ')' MAYBE_COMMENT NEWLINE BLOCKS END_ASSOCIATE- { let { startSpan = getSpan $1;- mLabel = Just $1;- TId _ name = $2;- mName = Just name;- abbrevs = fromReverseList $6;- body = reverse $10;- (endSpan, mEndLabel) = $11;- span = getTransSpan startSpan endSpan }- in BlAssociate () span mLabel mName abbrevs body mEndLabel }-| INTEGER_LITERAL associate '(' ABBREVIATIONS ')' MAYBE_COMMENT NEWLINE BLOCKS END_ASSOCIATE- { let { startSpan = getSpan $1;- mLabel = Just $1;- mName = Nothing;- abbrevs = fromReverseList $4;- body = reverse $8;- (endSpan, mEndLabel) = $9;- span = getTransSpan startSpan endSpan }- in BlAssociate () span mLabel mName abbrevs body mEndLabel }-| id ':' associate '(' ABBREVIATIONS ')' MAYBE_COMMENT NEWLINE BLOCKS END_ASSOCIATE- { let { startSpan = getSpan $1;- TId _ name = $1;- mLabel = Nothing;- mName = Just name;- abbrevs = fromReverseList $5;- body = reverse $9;- (endSpan, mEndLabel) = $10;- span = getTransSpan startSpan endSpan }- in BlAssociate () span mLabel mName abbrevs body mEndLabel }-| associate '(' ABBREVIATIONS ')' MAYBE_COMMENT NEWLINE BLOCKS END_ASSOCIATE- { let { startSpan = getSpan $1;- mLabel = Nothing;- mName = Nothing;- abbrevs = fromReverseList $3;- body = reverse $7;- (endSpan, mEndLabel) = $8;- span = getTransSpan startSpan endSpan }- in BlAssociate () span mLabel mName abbrevs body mEndLabel }---- TODO: Copied verbatim from END_IF. Should attempt to functionalise.-END_ASSOCIATE :: { (SrcSpan, Maybe (Expression A0)) }-: endassociate { (getSpan $1, Nothing) }-| endassociate id { (getSpan $2, Nothing) }-| INTEGER_LITERAL endassociate { (getSpan $2, Just $1) }-| INTEGER_LITERAL endassociate id { (getSpan $3, Just $1) }---- (var (ExpValue (ValVariable)), assoc. expr)-ABBREVIATIONS :: { [(ATuple Expression Expression A0)] }-: ABBREVIATIONS ',' ABBREVIATION { $3 : $1 }-| ABBREVIATION { [ $1 ] }--ABBREVIATION :: { ATuple Expression Expression A0 }-: VARIABLE '=>' EXPRESSION { ATuple () (getTransSpan $1 $3) $1 $3 }--ABSTRACTP :: { Bool }-: abstract { True }-| {- EMPTY -} { False }--MAYBE_EXPRESSION :: { Maybe (Expression A0) }-: EXPRESSION { Just $1 }-| {- EMPTY -} { Nothing }--MAYBE_COMMENT :: { Maybe Token }-: comment { Just $1 }-| {- EMPTY -} { Nothing }--SUBPROGRAM_UNITS2 :: { [ ProgramUnit A0 ] }-: SUBPROGRAM_UNITS SUBPROGRAM_UNIT NEWLINE { $2 : $1 }--MODULE_PROCEDURES :: { [ Block A0 ] }-: MODULE_PROCEDURES MODULE_PROCEDURE { $2 : $1 }-| MODULE_PROCEDURES MODULE_PROCEDURE COMMENT_BLOCK { $3 : $2 : $1 }-| { [ ] }--MODULE_PROCEDURE :: { Block A0 }-: moduleProcedure VARIABLES MAYBE_COMMENT NEWLINE- { let { al = fromReverseList $2;- st = StModuleProcedure () (getTransSpan $1 al) (fromReverseList $2) }- in BlStatement () (getTransSpan $1 $4) Nothing st }--COMMENT_BLOCK :: { Block A0 }-: comment NEWLINE { let (TComment s c) = $1 in BlComment () s (Comment c) }--MAYBE_NEWLINE :: { Maybe Token } : NEWLINE { Just $1 } | {- EMPTY -} { Nothing }--NEWLINE :: { Token }-: NEWLINE newline { $1 }-| NEWLINE ';' { $1 }-| newline { $1 }-| ';' { $1 }--STATEMENT :: { Statement A0 }-: NONEXECUTABLE_STATEMENT { $1 }-| EXECUTABLE_STATEMENT { $1 }--EXPRESSION_ASSIGNMENT_STATEMENT :: { Statement A0 }-: DATA_REF '=' EXPRESSION { StExpressionAssign () (getTransSpan $1 $3) $1 $3 }--NONEXECUTABLE_STATEMENT :: { Statement A0 }-: DECLARATION_STATEMENT { $1 }-| intent '(' INTENT_CHOICE ')' MAYBE_DCOLON EXPRESSION_LIST- { let expAList = fromReverseList $6- in StIntent () (getTransSpan $1 expAList) $3 expAList }-| optional MAYBE_DCOLON EXPRESSION_LIST- { let expAList = fromReverseList $3- in StOptional () (getTransSpan $1 expAList) expAList }-| public MAYBE_DCOLON EXPRESSION_LIST- { let expAList = fromReverseList $3- in StPublic () (getTransSpan $1 expAList) (Just expAList) }-| public { StPublic () (getSpan $1) Nothing }-| private MAYBE_DCOLON EXPRESSION_LIST- { let expAList = fromReverseList $3- in StPrivate () (getTransSpan $1 expAList) (Just expAList) }-| private { StPrivate () (getSpan $1) Nothing }-| protected MAYBE_DCOLON EXPRESSION_LIST- { let expAList = fromReverseList $3- in StProtected () (getTransSpan $1 expAList) (Just expAList) }-| protected { StProtected () (getSpan $1) Nothing }-| save MAYBE_DCOLON SAVE_ARGS- { let saveAList = (fromReverseList $3)- in StSave () (getTransSpan $1 saveAList) (Just saveAList) }-| save { StSave () (getSpan $1) Nothing }-| procedure '(' MAYBE_PROC_INTERFACE ')' ',' ATTRIBUTE_SPEC '::' PROC_DECLS- { let declAList = fromReverseList $8- in StProcedure () (getTransSpan $1 $8) $3 (Just $6) declAList }-| procedure '(' MAYBE_PROC_INTERFACE ')' MAYBE_DCOLON PROC_DECLS- { let declAList = fromReverseList $6- in StProcedure () (getTransSpan $1 $6) $3 Nothing declAList }-| dimension MAYBE_DCOLON INITIALIZED_DECLARATOR_LIST- { let declAList = fromReverseList $3- in StDimension () (getTransSpan $1 declAList) declAList }-| allocatable MAYBE_DCOLON INITIALIZED_DECLARATOR_LIST- { let declAList = fromReverseList $3- in StAllocatable () (getTransSpan $1 declAList) declAList }-| asynchronous MAYBE_DCOLON INITIALIZED_DECLARATOR_LIST- { let declAList = fromReverseList $3- in StAsynchronous () (getTransSpan $1 declAList) declAList }-| pointer MAYBE_DCOLON INITIALIZED_DECLARATOR_LIST- { let declAList = fromReverseList $3- in StPointer () (getTransSpan $1 declAList) declAList }-| target MAYBE_DCOLON INITIALIZED_DECLARATOR_LIST- { let declAList = fromReverseList $3- in StTarget () (getTransSpan $1 declAList) declAList }-| value MAYBE_DCOLON INITIALIZED_DECLARATOR_LIST- { let declAList = fromReverseList $3- in StValue () (getTransSpan $1 declAList) declAList }-| volatile MAYBE_DCOLON INITIALIZED_DECLARATOR_LIST- { let declAList = fromReverseList $3- in StVolatile () (getTransSpan $1 declAList) declAList }-| data cDATA DATA_GROUPS cPOP- { let dataAList = fromReverseList $3- in StData () (getTransSpan $1 dataAList) dataAList }-| parameter '(' PARAMETER_ASSIGNMENTS ')'- { let declAList = fromReverseList $3- in StParameter () (getTransSpan $1 $4) declAList }-| implicit none { StImplicit () (getTransSpan $1 $2) Nothing }-| implicit cIMPLICIT IMP_LISTS cPOP- { let impAList = fromReverseList $3- in StImplicit () (getTransSpan $1 impAList) $ Just $ impAList }-| namelist cNAMELIST NAMELISTS cPOP- { let nameALists = fromReverseList $3- in StNamelist () (getTransSpan $1 nameALists) nameALists }-| equivalence EQUIVALENCE_GROUPS- { let eqALists = fromReverseList $2- in StEquivalence () (getTransSpan $1 eqALists) eqALists }-| common cCOMMON COMMON_GROUPS cPOP- { let commonAList = fromReverseList $3- in StCommon () (getTransSpan $1 commonAList) commonAList }-| external MAYBE_DCOLON VARIABLES- { let alist = fromReverseList $3- in StExternal () (getTransSpan $1 alist) alist }-| intrinsic MAYBE_DCOLON VARIABLES- { let alist = fromReverseList $3- in StIntrinsic () (getTransSpan $1 alist) alist }-| use MODULE_NATURE VARIABLE { StUse () (getTransSpan $1 $3) $3 $2 Permissive Nothing }-| use MODULE_NATURE VARIABLE ',' RENAME_LIST- { let alist = fromReverseList $5- in StUse () (getTransSpan $1 alist) $3 $2 Permissive (Just alist) }-| use MODULE_NATURE VARIABLE ',' only ':' MAYBE_RENAME_LIST- { StUse () (getTransSpan $1 ($6, $7)) $3 $2 Exclusive $7 }-| entry VARIABLE MAYBE_RESULT- { StEntry () (getTransSpan $1 $ maybe (getSpan $2) getSpan $3) $2 Nothing $3 }-| entry VARIABLE '(' ')' MAYBE_RESULT- { StEntry () (getTransSpan $1 $ maybe (getSpan $4) getSpan $5) $2 Nothing $5 }-| entry VARIABLE '(' VARIABLES ')' MAYBE_RESULT- { StEntry () (getTransSpan $1 $ maybe (getSpan $5) getSpan $6) $2 (Just $ fromReverseList $4) $6 }-| sequence { StSequence () (getSpan $1) }-| type ATTRIBUTE_LIST '::' id- { let { TId span id = $4;- alist = if null $2 then Nothing else (Just . fromReverseList) $2 }- in StType () (getTransSpan $1 span) alist id }-| type id- { let TId span id = $2 in StType () (getTransSpan $1 span) Nothing id }-| endType { StEndType () (getSpan $1) Nothing }-| endType id- { let TId span id = $2 in StEndType () (getTransSpan $1 span) (Just id) }--- R461-R464-| enum ',' bind '(' 'c' ')' { StEnum () (getTransSpan $1 $6) }-| enumerator MAYBE_DCOLON ENUMERATOR_LIST { StEnumerator () (getTransSpan $1 $3) (fromReverseList $3) }-| endEnum { StEndEnum () (getSpan $1) }-| include STRING { StInclude () (getTransSpan $1 $2) $2 Nothing }--- R1209-| import '::' IMPORT_NAME_LIST { StImport () (getTransSpan $1 $3) (fromReverseList $3) }-| import IMPORT_NAME_LIST { StImport () (getTransSpan $1 $2) (fromReverseList $2) }--- Following is a fake node to make arbitrary FORMAT statements parsable.--- Must be fixed in the future. TODO-| format blob- { let TBlob s blob = $2 in StFormatBogus () (getTransSpan $1 s) blob }--ENUMERATOR_LIST :: { [Declarator A0] }-: ENUMERATOR_LIST ',' ENUMERATOR { $3:$1 }-| ENUMERATOR { [$1] }---- R463-ENUMERATOR :: { Declarator A0 }-: PARAMETER_ASSIGNMENT { $1 }-| VARIABLE { Declarator () (getSpan $1) $1 ScalarDecl Nothing Nothing }--MAYBE_PROC_INTERFACE :: { Maybe (ProcInterface A0) }-: TYPE_SPEC { Just $ ProcInterfaceType () (getSpan $1) $1 }-| VARIABLE { Just $ ProcInterfaceName () (getSpan $1) $1 }-| {- EMPTY -} { Nothing }--PROC_DECLS :: { [ProcDecl A0] }-: PROC_DECLS ',' PROC_DECL { $3 : $1 }-| PROC_DECL { [ $1 ] }--PROC_DECL :: { ProcDecl A0 }-: VARIABLE '=>' EXPRESSION { ProcDecl () (getTransSpan $1 $3) $1 (Just $3) }-| VARIABLE { ProcDecl () (getSpan $1) $1 Nothing }--MODULE_NATURE :: { Maybe ModuleNature }-: ',' intrinsic '::' { Just ModIntrinsic }-| ',' nonintrinsic '::' { Just ModNonIntrinsic }-| '::' { Nothing }-| {- empty -} { Nothing }--EXECUTABLE_STATEMENT :: { Statement A0 }-: allocate '(' MAYBE_TYPE_SPEC DATA_REFS MAYBE_ALLOC_OPT_LIST ')'- { StAllocate () (getTransSpan $1 $6) $3 (fromReverseList $4) $5 }-| nullify '(' DATA_REFS ')'- { StNullify () (getTransSpan $1 $4) (fromReverseList $3) }-| deallocate '(' DATA_REFS MAYBE_ALLOC_OPT_LIST ')'- { StDeallocate () (getTransSpan $1 $5) (fromReverseList $3) $4 }-| EXPRESSION_ASSIGNMENT_STATEMENT { $1 }-| POINTER_ASSIGNMENT_STMT { $1 }-| where '(' EXPRESSION ')' EXPRESSION_ASSIGNMENT_STATEMENT- { StWhere () (getTransSpan $1 $5) $3 $5 }-| id ':' where '(' EXPRESSION ')' { let (TId s1 id) = $1 in StWhereConstruct () (getTransSpan $1 $6) (Just id) $5 }-| where '(' EXPRESSION ')' { StWhereConstruct () (getTransSpan $1 $4) Nothing $3 }-| elsewhere '(' EXPRESSION ')' id { let TId _ id = $5 in StElsewhere () (getTransSpan $1 $5) (Just id) (Just $3) }-| elsewhere '(' EXPRESSION ')' { StElsewhere () (getTransSpan $1 $4) Nothing (Just $3) }-| elsewhere id { let TId _ id = $2 in StElsewhere () (getTransSpan $1 $2) (Just id) Nothing }-| elsewhere { StElsewhere () (getSpan $1) Nothing Nothing }-| endwhere id { let TId _ id = $2 in StEndWhere () (getTransSpan $1 $2) (Just id) }-| endwhere { StEndWhere () (getSpan $1) Nothing }-| if '(' EXPRESSION ')' INTEGER_LITERAL ',' INTEGER_LITERAL ',' INTEGER_LITERAL- { StIfArithmetic () (getTransSpan $1 $9) $3 $5 $7 $9 }-| do { StDo () (getSpan $1) Nothing Nothing Nothing }-| id ':' do- { let TId s id = $1- in StDo () (getTransSpan s $3) (Just id) Nothing Nothing }-| do INTEGER_LITERAL MAYBE_COMMA DO_SPECIFICATION- { StDo () (getTransSpan $1 $4) Nothing (Just $2) (Just $4) }-| do DO_SPECIFICATION { StDo () (getTransSpan $1 $2) Nothing Nothing (Just $2) }-| id ':' do DO_SPECIFICATION- { let TId s id = $1- in StDo () (getTransSpan s $4) (Just id) Nothing (Just $4) }-| do INTEGER_LITERAL MAYBE_COMMA while '(' EXPRESSION ')'- { StDoWhile () (getTransSpan $1 $7) Nothing (Just $2) $6 }-| do while '(' EXPRESSION ')'- { StDoWhile () (getTransSpan $1 $5) Nothing Nothing $4 }-| id ':' do while '(' EXPRESSION ')'- { let TId s id = $1- in StDoWhile () (getTransSpan s $7) (Just id) Nothing $6 }-| enddo { StEnddo () (getSpan $1) Nothing }-| enddo id- { let TId s id = $2 in StEnddo () (getTransSpan $1 s) (Just id) }-| cycle { StCycle () (getSpan $1) Nothing }-| cycle VARIABLE { StCycle () (getTransSpan $1 $2) (Just $2) }-| exit { StExit () (getSpan $1) Nothing }-| exit VARIABLE { StExit () (getTransSpan $1 $2) (Just $2) }--- GO TO label-| goto INTEGER_LITERAL { StGotoUnconditional () (getTransSpan $1 $2) $2 }--- GO TO label-list [,] scalar-int-expression-| goto '(' INTEGERS ')' MAYBE_COMMA EXPRESSION- { StGotoComputed () (getTransSpan $1 $6) (fromReverseList $3) $6 }-| continue { StContinue () (getSpan $1) }-| stop { StStop () (getSpan $1) Nothing }-| stop EXPRESSION { StStop () (getTransSpan $1 $2) (Just $2) }-| if '(' EXPRESSION ')' EXECUTABLE_STATEMENT- { StIfLogical () (getTransSpan $1 $5) $3 $5 }-| read CILIST IN_IOLIST- { let alist = fromReverseList $3- in StRead () (getTransSpan $1 alist) $2 (Just alist) }-| read CILIST { StRead () (getTransSpan $1 $2) $2 Nothing }-| read FORMAT_ID ',' IN_IOLIST- { let alist = fromReverseList $4- in StRead2 () (getTransSpan $1 alist) $2 (Just alist) }-| read FORMAT_ID { StRead2 () (getTransSpan $1 $2) $2 Nothing }-| write CILIST OUT_IOLIST- { let alist = fromReverseList $3- in StWrite () (getTransSpan $1 alist) $2 (Just alist) }-| write CILIST { StWrite () (getTransSpan $1 $2) $2 Nothing }-| print FORMAT_ID ',' OUT_IOLIST- { let alist = fromReverseList $4- in StPrint () (getTransSpan $1 alist) $2 (Just alist) }-| print FORMAT_ID { StPrint () (getTransSpan $1 $2) $2 Nothing }-| open CILIST { StOpen () (getTransSpan $1 $2) $2 }-| close CILIST { StClose () (getTransSpan $1 $2) $2 }-| inquire CILIST { StInquire () (getTransSpan $1 $2) $2 }-| rewind CILIST { StRewind () (getTransSpan $1 $2) $2 }-| rewind UNIT { StRewind2 () (getTransSpan $1 $2) $2 }-| endfile CILIST { StEndfile () (getTransSpan $1 $2) $2 }-| endfile UNIT { StEndfile2 () (getTransSpan $1 $2) $2 }-| backspace CILIST { StBackspace () (getTransSpan $1 $2) $2 }-| backspace UNIT { StBackspace2 () (getTransSpan $1 $2) $2 }-| flush INTEGER_LITERAL { StFlush () (getTransSpan $1 $2) (AList () (getSpan $2) [FSUnit () (getSpan $2) $2]) }-| flush '(' FLUSH_SPEC_LIST ')' { StFlush () (getTransSpan $1 $4) (fromReverseList $3) }-| call VARIABLE { StCall () (getTransSpan $1 $2) $2 Nothing }-| call VARIABLE '(' ')' { StCall () (getTransSpan $1 $4) $2 Nothing }-| call VARIABLE '(' ARGUMENTS ')'- { let alist = fromReverseList $4- in StCall () (getTransSpan $1 $5) $2 (Just alist) }-| return { StReturn () (getSpan $1) Nothing }-| return EXPRESSION { StReturn () (getTransSpan $1 $2) (Just $2) }-| FORALL { $1 }-| END_FORALL { $1 }--ARGUMENTS :: { [ Argument A0 ] }-: ARGUMENTS ',' ARGUMENT { $3 : $1 }-| ARGUMENT { [ $1 ] }--ARGUMENT :: { Argument A0 }-: id '=' EXPRESSION- { let TId span keyword = $1- in Argument () (getTransSpan span $3) (Just keyword) $3 }-| EXPRESSION- { Argument () (getSpan $1) Nothing $1 }--MAYBE_RENAME_LIST :: { Maybe (AList Use A0) }-: RENAME_LIST { Just $ fromReverseList $1 }-| {- empty -} { Nothing }--RENAME_LIST :: { [ Use A0 ] }-: RENAME_LIST ',' RENAME { $3 : $1 }-| RENAME { [ $1 ] }--RENAME :: { Use A0 }-: VARIABLE '=>' VARIABLE { UseRename () (getTransSpan $1 $3) $1 $3 }-| VARIABLE { UseID () (getSpan $1) $1 }-| operator '(' opCustom ')'- { let TOpCustom ss op = $3- in UseID () (getTransSpan $1 $4) (ExpValue () ss (ValOperator op)) }-| assignment { UseID () (getSpan $1) (ExpValue () (getSpan $1) ValAssignment) }--MAYBE_DCOLON :: { () } : '::' { () } | {- EMPTY -} { () }--FORMAT_ID :: { Expression A0 }-: FORMAT_ID '/' '/' FORMAT_ID %prec CONCAT- { ExpBinary () (getTransSpan $1 $4) Concatenation $1 $4 }-| INTEGER_LITERAL { $1 }-| STRING { $1 }-| DATA_REF { $1 }-| '*' { ExpValue () (getSpan $1) ValStar }--UNIT :: { Expression A0 }-: INTEGER_LITERAL { $1 }-| DATA_REF { $1 }-| '*' { ExpValue () (getSpan $1) ValStar }--{- R928 -}-FLUSH_SPEC_LIST :: { [ FlushSpec A0 ] }-: FLUSH_SPEC_LIST ',' FLUSH_SPEC { $3 : $1 }-| FLUSH_SPEC { [ $1 ] }--{- R928 -}-FLUSH_SPEC :: { FlushSpec A0 }-: EXPRESSION { FSUnit () (getSpan $1) $1 }-| unit '=' EXPRESSION { FSUnit () (getTransSpan $1 $3) $3 }-| iostat '=' EXPRESSION { FSIOStat () (getTransSpan $1 $3) $3 }-| iomsg '=' EXPRESSION { FSIOMsg () (getTransSpan $1 $3) $3 }-| err '=' EXPRESSION { FSErr () (getTransSpan $1 $3) $3 }--CILIST :: { AList ControlPair A0 }-: '(' CILIST_ELEMENT ',' FORMAT_ID ',' CILIST_PAIRS ')'- { let { cp1 = ControlPair () (getSpan $2) Nothing $2;- cp2 = ControlPair () (getSpan $4) Nothing $4;- tail = fromReverseList $6 }- in setSpan (getTransSpan $1 $7) $ cp1 `aCons` cp2 `aCons` tail }-| '(' CILIST_ELEMENT ',' FORMAT_ID ')'- { let { cp1 = ControlPair () (getSpan $2) Nothing $2;- cp2 = ControlPair () (getSpan $4) Nothing $4 }- in AList () (getTransSpan $1 $5) [ cp1, cp2 ] }-| '(' CILIST_ELEMENT ',' CILIST_PAIRS ')'- { let { cp1 = ControlPair () (getSpan $2) Nothing $2;- tail = fromReverseList $4 }- in setSpan (getTransSpan $1 $5) $ cp1 `aCons` tail }-| '(' CILIST_ELEMENT ')'- { let cp1 = ControlPair () (getSpan $2) Nothing $2- in AList () (getTransSpan $1 $3) [ cp1 ] }-| '(' CILIST_PAIRS ')' { fromReverseList $2 }--CILIST_PAIRS :: { [ ControlPair A0 ] }-: CILIST_PAIRS ',' CILIST_PAIR { $3 : $1 }-| CILIST_PAIR { [ $1 ] }--CILIST_PAIR :: { ControlPair A0 }-: id '=' CILIST_ELEMENT- { let (TId s id) = $1 in ControlPair () (getTransSpan s $3) (Just id) $3 }--CILIST_ELEMENT :: { Expression A0 }-: CI_EXPRESSION { $1 }-| '*' { ExpValue () (getSpan $1) ValStar }--CI_EXPRESSION :: { Expression A0 }-: CI_EXPRESSION '+' CI_EXPRESSION- { ExpBinary () (getTransSpan $1 $3) Addition $1 $3 }-| CI_EXPRESSION '-' CI_EXPRESSION- { ExpBinary () (getTransSpan $1 $3) Subtraction $1 $3 }-| CI_EXPRESSION '*' CI_EXPRESSION- { ExpBinary () (getTransSpan $1 $3) Multiplication $1 $3 }-| CI_EXPRESSION '/' CI_EXPRESSION- { ExpBinary () (getTransSpan $1 $3) Division $1 $3 }-| CI_EXPRESSION '**' CI_EXPRESSION- { ExpBinary () (getTransSpan $1 $3) Exponentiation $1 $3 }-| CI_EXPRESSION '/' '/' CI_EXPRESSION %prec CONCAT- { ExpBinary () (getTransSpan $1 $4) Concatenation $1 $4 }-| ARITHMETIC_SIGN CI_EXPRESSION %prec SIGN- { ExpUnary () (getTransSpan (fst $1) $2) (snd $1) $2 }-| CI_EXPRESSION or CI_EXPRESSION- { ExpBinary () (getTransSpan $1 $3) Or $1 $3 }-| CI_EXPRESSION and CI_EXPRESSION- { ExpBinary () (getTransSpan $1 $3) And $1 $3 }-| not CI_EXPRESSION- { ExpUnary () (getTransSpan $1 $2) Not $2 }-| CI_EXPRESSION eqv CI_EXPRESSION- { ExpBinary () (getTransSpan $1 $3) Equivalent $1 $3 }-| CI_EXPRESSION neqv CI_EXPRESSION- { ExpBinary () (getTransSpan $1 $3) NotEquivalent $1 $3 }-| CI_EXPRESSION RELATIONAL_OPERATOR CI_EXPRESSION %prec RELATIONAL- { ExpBinary () (getTransSpan $1 $3) $2 $1 $3 }-| opCustom CI_EXPRESSION %prec DEFINED_UNARY- { let TOpCustom span str = $1- in ExpUnary () (getTransSpan span $2) (UnCustom str) $2 }-| CI_EXPRESSION opCustom CI_EXPRESSION- { let TOpCustom _ str = $2- in ExpBinary () (getTransSpan $1 $3) (BinCustom str) $1 $3 }-| '(' CI_EXPRESSION ')' { setSpan (getTransSpan $1 $3) $2 }-| INTEGER_LITERAL { $1 }-| LOGICAL_LITERAL { $1 }-| STRING { $1 }-| DATA_REF { $1 }--MAYBE_ALLOC_OPT_LIST :: { Maybe (AList AllocOpt A0) }-: ',' ALLOC_OPT_LIST { Just $ fromReverseList $2 }-| {- empty -} { Nothing }--ALLOC_OPT_LIST :: { [ AllocOpt A0 ] }-: ALLOC_OPT_LIST ',' ALLOC_OPT { $3 : $1 }-| ALLOC_OPT { [ $1 ] }--{- R624 -}-ALLOC_OPT :: { AllocOpt A0 }-: stat '=' EXPRESSION { AOStat () (getTransSpan $1 $3) $3 }-| errmsg '=' EXPRESSION { AOErrMsg () (getTransSpan $1 $3) $3 }-| source '=' EXPRESSION { AOSource () (getTransSpan $1 $3) $3 }--IN_IOLIST :: { [ Expression A0 ] }-: IN_IOLIST ',' IN_IO_ELEMENT { $3 : $1}-| IN_IO_ELEMENT { [ $1 ] }--IN_IO_ELEMENT :: { Expression A0 }-: DATA_REF { $1 }-| '(' IN_IOLIST ',' DO_SPECIFICATION ')'- { ExpImpliedDo () (getTransSpan $1 $5) (fromReverseList $2) $4 }--OUT_IOLIST :: { [ Expression A0 ] }-: OUT_IOLIST ',' EXPRESSION { $3 : $1}-| EXPRESSION { [ $1 ] }--COMMON_GROUPS :: { [ CommonGroup A0 ] }-: COMMON_GROUPS COMMON_GROUP { $2 : $1 }-| COMMON_GROUPS ',2' COMMON_GROUP { $3 : $1 }-| INIT_COMMON_GROUP { [ $1 ] }--COMMON_GROUP :: { CommonGroup A0 }-: COMMON_NAME UNINITIALIZED_DECLARATOR_LIST- { let alist = fromReverseList $2- in CommonGroup () (getTransSpan $1 alist) (Just $1) alist }-| '/' '/' UNINITIALIZED_DECLARATOR_LIST- { let alist = fromReverseList $3- in CommonGroup () (getTransSpan $1 alist) Nothing alist }--INIT_COMMON_GROUP :: { CommonGroup A0 }-: COMMON_NAME UNINITIALIZED_DECLARATOR_LIST- { let alist = fromReverseList $2- in CommonGroup () (getTransSpan $1 alist) (Just $1) alist }-| '/' '/' UNINITIALIZED_DECLARATOR_LIST- { let alist = fromReverseList $3- in CommonGroup () (getTransSpan $1 alist) Nothing alist }-| UNINITIALIZED_DECLARATOR_LIST- { let alist = fromReverseList $1- in CommonGroup () (getSpan alist) Nothing alist }--EQUIVALENCE_GROUPS :: { [ AList Expression A0 ] }-: EQUIVALENCE_GROUPS ',' '(' PART_REFS ')'- { setSpan (getTransSpan $3 $5) (fromReverseList $4) : $1 }-| '(' PART_REFS ')'- { [ setSpan (getTransSpan $1 $3) (fromReverseList $2) ] }--NAMELISTS :: { [ Namelist A0 ] }-: NAMELISTS NAMELIST { $2 : $1 }-| NAMELISTS ',2' NAMELIST { $3 : $1 }-| NAMELIST { [ $1 ] }--NAMELIST :: { Namelist A0 }-: '/' VARIABLE '/' VARIABLES- { Namelist () (getTransSpan $1 $4) $2 $ fromReverseList $4 }--MAYBE_VARIABLES :: { Maybe (AList Expression A0) }-: VARIABLES { Just $ fromReverseList $1 } | {- EMPTY -} { Nothing }--VARIABLES :: { [ Expression A0 ] }-: VARIABLES ',' VARIABLE { $3 : $1 }-| VARIABLE { [ $1 ] }--IMP_LISTS :: { [ ImpList A0 ] }-: IMP_LISTS ',' IMP_LIST { $3 : $1 }-| IMP_LIST { [ $1 ] }--IMP_LIST :: { ImpList A0 }-: TYPE_SPEC '(2' IMP_ELEMENTS ')'- { ImpList () (getTransSpan $1 $4) $1 (aReverse $3) }--IMP_ELEMENTS :: { AList ImpElement A0 }-: IMP_ELEMENTS ',' IMP_ELEMENT { setSpan (getTransSpan $1 $3) $ $3 `aCons` $1 }-| IMP_ELEMENT { AList () (getSpan $1) [ $1 ] }--IMP_ELEMENT :: { ImpElement A0 }-: id {% do- let (TId s id) = $1- if length id /= 1- then fail "Implicit argument must be a character."- else return $ ImpCharacter () s id- }-| id '-' id {% do- let (TId _ id1) = $1- let (TId _ id2) = $3- if length id1 /= 1 || length id2 /= 1- then fail "Implicit argument must be a character."- else return $ ImpRange () (getTransSpan $1 $3) id1 id2- }--PARAMETER_ASSIGNMENTS :: { [ Declarator A0 ] }-: PARAMETER_ASSIGNMENTS ',' PARAMETER_ASSIGNMENT { $3 : $1 }-| PARAMETER_ASSIGNMENT { [ $1 ] }--PARAMETER_ASSIGNMENT :: { Declarator A0 }-: VARIABLE '=' EXPRESSION- { Declarator () (getTransSpan $1 $3) $1 ScalarDecl Nothing (Just $3) }--DECLARATION_STATEMENT :: { Statement A0 }-: TYPE_SPEC ATTRIBUTE_LIST '::' INITIALIZED_DECLARATOR_LIST- { let { mAttrAList = if null $2 then Nothing else Just $ fromReverseList $2;- declAList = fromReverseList $4 }- in StDeclaration () (getTransSpan $1 declAList) $1 mAttrAList declAList }-| TYPE_SPEC INITIALIZED_DECLARATOR_LIST- { let { declAList = fromReverseList $2 }- in StDeclaration () (getTransSpan $1 declAList) $1 Nothing declAList }--ATTRIBUTE_LIST :: { [ Attribute A0 ] }-: ATTRIBUTE_LIST ',' ATTRIBUTE_SPEC { $3 : $1 }-| {- EMPTY -} { [ ] }--ATTRIBUTE_SPEC :: { Attribute A0 }-: public { AttrPublic () (getSpan $1) }-| private { AttrPrivate () (getSpan $1) }-| protected { AttrProtected () (getSpan $1) }-| allocatable { AttrAllocatable () (getSpan $1) }-| asynchronous { AttrAsynchronous () (getSpan $1) }-| dimension '(' DIMENSION_DECLARATORS ')'- { AttrDimension () (getTransSpan $1 $4) (aReverse $3) }-| external { AttrExternal () (getSpan $1) }-| intent '(' INTENT_CHOICE ')' { AttrIntent () (getTransSpan $1 $4) $3 }-| intrinsic { AttrIntrinsic () (getSpan $1) }-| optional { AttrOptional () (getSpan $1) }-| pointer { AttrPointer () (getSpan $1) }-| parameter { AttrParameter () (getSpan $1) }-| save { AttrSave () (getSpan $1) }-| target { AttrTarget () (getSpan $1) }-| value { AttrValue () (getSpan $1) }-| volatile { AttrVolatile () (getSpan $1) }-| SUFFIX { AttrSuffix () (getSpan $1) $1 }--INTENT_CHOICE :: { Intent } : in { In } | out { Out } | inout { InOut }--DATA_GROUPS :: { [ DataGroup A0 ] }-: DATA_GROUPS MAYBE_COMMA DATA_LIST slash EXPRESSION_LIST slash- { let { nameAList = fromReverseList $3;- dataAList = fromReverseList $5 }- in DataGroup () (getTransSpan nameAList $6) nameAList dataAList : $1 }-| DATA_LIST slash EXPRESSION_LIST slash- { let { nameAList = fromReverseList $1;- dataAList = fromReverseList $3 }- in [ DataGroup () (getTransSpan nameAList $4) nameAList dataAList ] }--MAYBE_COMMA :: { () } : ',' { () } | {- EMPTY -} { () }--DATA_LIST :: { [ Expression A0 ] }-: DATA_LIST ',' DATA_ELEMENT { $3 : $1 }-| DATA_ELEMENT { [ $1 ] }--DATA_ELEMENT :: { Expression A0 }-: DATA_REF { $1 } | IMPLIED_DO { $1 }--SAVE_ARGS :: { [ Expression A0 ] }-: SAVE_ARGS ',' SAVE_ARG { $3 : $1 } | SAVE_ARG { [ $1 ] }--SAVE_ARG :: { Expression A0 } : COMMON_NAME { $1 } | VARIABLE { $1 }--COMMON_NAME :: { Expression A0 }-: '/' VARIABLE '/' { setSpan (getTransSpan $1 $3) $2 }--INITIALIZED_DECLARATOR_LIST :: { [ Declarator A0 ] }-: INITIALIZED_DECLARATOR_LIST ',' INITIALIZED_DECLARATOR { $3 : $1 }-| INITIALIZED_DECLARATOR { [ $1 ] }--UNINITIALIZED_DECLARATOR_LIST :: { [ Declarator A0 ] }-: UNINITIALIZED_DECLARATOR_LIST ',' DECLARATOR { $3 : $1 }-| DECLARATOR { [ $1 ] }--INITIALIZED_DECLARATOR :: { Declarator A0 }-: DECLARATOR '=' EXPRESSION { setInitialisation $1 $3 }-| DECLARATOR '=>' EXPRESSION { setInitialisation $1 $3 }-| DECLARATOR { $1 }--DECLARATOR :: { Declarator A0 }-: VARIABLE- { Declarator () (getSpan $1) $1 ScalarDecl Nothing Nothing }-| VARIABLE '*' EXPRESSION- { Declarator () (getTransSpan $1 $3) $1 ScalarDecl (Just $3) Nothing }-| VARIABLE '*' '(' '*' ')'- { let star = ExpValue () (getSpan $4) ValStar- in Declarator () (getTransSpan $1 $5) $1 ScalarDecl (Just star) Nothing }-| VARIABLE '(' DIMENSION_DECLARATORS ')'- { Declarator () (getTransSpan $1 $4) $1 (ArrayDecl (aReverse $3)) Nothing Nothing }-| VARIABLE '(' DIMENSION_DECLARATORS ')' '*' EXPRESSION- { Declarator () (getTransSpan $1 $6) $1 (ArrayDecl (aReverse $3)) (Just $6) Nothing }--- nonstandard char array syntax (wrong order for dimensions & charlen)-| VARIABLE '*' EXPRESSION '(' DIMENSION_DECLARATORS ')'- { Declarator () (getTransSpan $1 $6) $1 (ArrayDecl (aReverse $5)) (Just $3) Nothing }-| VARIABLE '(' DIMENSION_DECLARATORS ')' '*' '(' '*' ')'- { let star = ExpValue () (getSpan $7) ValStar- in Declarator () (getTransSpan $1 $8) $1 (ArrayDecl (aReverse $3)) (Just star) Nothing }--DIMENSION_DECLARATORS :: { AList DimensionDeclarator A0 }-: DIMENSION_DECLARATORS ',' DIMENSION_DECLARATOR- { setSpan (getTransSpan $1 $3) $ $3 `aCons` $1 }-| DIMENSION_DECLARATOR- { AList () (getSpan $1) [ $1 ] }--DIMENSION_DECLARATOR :: { DimensionDeclarator A0 }-: EXPRESSION ':' EXPRESSION- { DimensionDeclarator () (getTransSpan $1 $3) (Just $1) (Just $3) }-| EXPRESSION { DimensionDeclarator () (getSpan $1) Nothing (Just $1) }--- Lower bound only-| EXPRESSION ':'- { DimensionDeclarator () (getTransSpan $1 $2) (Just $1) Nothing }-| EXPRESSION ':' '*'- { let { span = getSpan $3;- star = ExpValue () span ValStar }- in DimensionDeclarator () (getTransSpan $1 span) (Just $1) (Just star) }-| '*'- { let { span = getSpan $1;- star = ExpValue () span ValStar }- in DimensionDeclarator () span Nothing (Just star) }-| ':'- { let span = getSpan $1- in DimensionDeclarator () span Nothing Nothing }--MAYBE_TYPE_SPEC :: { Maybe (TypeSpec A0) }-: TYPE_SPEC '::' { Just $1 }-| {- empty -} { Nothing }--TYPE_SPEC :: { TypeSpec A0 }-: integer KIND_SELECTOR { TypeSpec () (getSpan ($1, $2)) TypeInteger $2 }-| real KIND_SELECTOR { TypeSpec () (getSpan ($1, $2)) TypeReal $2 }-| doublePrecision { TypeSpec () (getSpan $1) TypeDoublePrecision Nothing }-| complex KIND_SELECTOR { TypeSpec () (getSpan ($1, $2)) TypeComplex $2 }-| character CHAR_SELECTOR { TypeSpec () (getSpan ($1, $2)) TypeCharacter $2 }-| logical KIND_SELECTOR { TypeSpec () (getSpan ($1, $2)) TypeLogical $2 }-| type '(' id ')'- { let TId _ id = $3- in TypeSpec () (getTransSpan $1 $4) (TypeCustom id) Nothing }--- R502-| class '(' '*' ')' { TypeSpec () (getSpan ($1, $4)) ClassStar Nothing }--- FIXME: this (and TypeCustom) can accept parameterised types. See type-param-value.--- Needs refactoring as this is used in various parts of the spec to consolidate--- uses of ':', '*' and scalar-int-exp.-| class '(' id ')'- { let TId _ id = $3- in TypeSpec () (getSpan ($1, $4)) (ClassCustom id) Nothing }--KIND_SELECTOR :: { Maybe (Selector A0) }-: '(' EXPRESSION ')'- { Just $ Selector () (getTransSpan $1 $3) Nothing (Just $2) }-| '(' kind '=' EXPRESSION ')'- { Just $ Selector () (getTransSpan $1 $5) Nothing (Just $4) }-| '*' EXPRESSION -- non-standard but commonly used extension- { Just $ Selector () (getTransSpan $1 $2) Nothing (Just $2) }-| {- EMPTY -} { Nothing }--CHAR_SELECTOR :: { Maybe (Selector A0) }-: '*' EXPRESSION- { Just $ Selector () (getTransSpan $1 $2) (Just $2) Nothing }--- The following rule is a bug in the spec.--- | '*' EXPRESSION ','--- { Just $ Selector () (getTransSpan $1 $2) (Just $2) Nothing }-| '*' '(' '*' ')'- { let star = ExpValue () (getSpan $3) ValStar- in Just $ Selector () (getTransSpan $1 $4) (Just star) Nothing }-| '(' LEN_EXPRESSION ')'- { Just $ Selector () (getTransSpan $1 $3) (Just $2) Nothing }-| '(' len '=' LEN_EXPRESSION ')'- { Just $ Selector () (getTransSpan $1 $5) (Just $4) Nothing }-| '(' kind '=' EXPRESSION ')'- { Just $ Selector () (getTransSpan $1 $5) Nothing (Just $4) }-| '(' LEN_EXPRESSION ',' EXPRESSION ')'- { Just $ Selector () (getTransSpan $1 $5) (Just $2) (Just $4) }-| '(' LEN_EXPRESSION ',' kind '=' EXPRESSION ')'- { Just $ Selector () (getTransSpan $1 $7) (Just $2) (Just $6) }-| '(' len '=' LEN_EXPRESSION ',' kind '=' EXPRESSION ')'- { Just $ Selector () (getTransSpan $1 $9) (Just $4) (Just $8) }-| '(' kind '=' EXPRESSION ',' len '=' LEN_EXPRESSION ')'- { Just $ Selector () (getTransSpan $1 $9) (Just $8) (Just $4) }-| {- EMPTY -} { Nothing }--{- R402 -}-LEN_EXPRESSION :: { Expression A0 }-: EXPRESSION { $1 }-| '*' { ExpValue () (getSpan $1) ValStar }-| ':' { ExpValue () (getSpan $1) ValColon }--EXPRESSION :: { Expression A0 }-: EXPRESSION '+' EXPRESSION- { ExpBinary () (getTransSpan $1 $3) Addition $1 $3 }-| EXPRESSION '-' EXPRESSION- { ExpBinary () (getTransSpan $1 $3) Subtraction $1 $3 }-| EXPRESSION '*' EXPRESSION- { ExpBinary () (getTransSpan $1 $3) Multiplication $1 $3 }-| EXPRESSION '/' EXPRESSION- { ExpBinary () (getTransSpan $1 $3) Division $1 $3 }-| EXPRESSION '**' EXPRESSION- { ExpBinary () (getTransSpan $1 $3) Exponentiation $1 $3 }-| EXPRESSION '/' '/' EXPRESSION %prec CONCAT- { ExpBinary () (getTransSpan $1 $4) Concatenation $1 $4 }-| ARITHMETIC_SIGN EXPRESSION %prec SIGN- { ExpUnary () (getTransSpan (fst $1) $2) (snd $1) $2 }-| EXPRESSION or EXPRESSION- { ExpBinary () (getTransSpan $1 $3) Or $1 $3 }-| EXPRESSION and EXPRESSION- { ExpBinary () (getTransSpan $1 $3) And $1 $3 }-| not EXPRESSION- { ExpUnary () (getTransSpan $1 $2) Not $2 }-| EXPRESSION eqv EXPRESSION- { ExpBinary () (getTransSpan $1 $3) Equivalent $1 $3 }-| EXPRESSION neqv EXPRESSION- { ExpBinary () (getTransSpan $1 $3) NotEquivalent $1 $3 }-| EXPRESSION RELATIONAL_OPERATOR EXPRESSION %prec RELATIONAL- { ExpBinary () (getTransSpan $1 $3) $2 $1 $3 }-| opCustom EXPRESSION %prec DEFINED_UNARY- { let TOpCustom span str = $1- in ExpUnary () (getTransSpan span $2) (UnCustom str) $2 }-| EXPRESSION opCustom EXPRESSION- { let TOpCustom _ str = $2- in ExpBinary () (getTransSpan $1 $3) (BinCustom str) $1 $3 }-| '(' EXPRESSION ')' { setSpan (getTransSpan $1 $3) $2 }-| NUMERIC_LITERAL { $1 }-| '(' EXPRESSION ',' EXPRESSION ')'- { ExpValue () (getTransSpan $1 $5) (ValComplex $2 $4) }-| LOGICAL_LITERAL { $1 }-| STRING { $1 }-| DATA_REF { $1 }-| IMPLIED_DO { $1 }-| '(/' EXPRESSION_LIST '/)'- { ExpInitialisation () (getTransSpan $1 $3) (fromReverseList $2) }-| operator '(' opCustom ')'- { let TOpCustom _ op = $3- in ExpValue () (getTransSpan $1 $4) (ValOperator op) }-| assignment { ExpValue () (getSpan $1) ValAssignment }-| '*' INTEGER_LITERAL { ExpReturnSpec () (getTransSpan $1 $2) $2 }--DATA_REFS :: { [ Expression A0 ] }-: DATA_REFS ',' DATA_REF { $3 : $1 }-| DATA_REF { [ $1 ] }--DATA_REF :: { Expression A0 }-: DATA_REF '%' PART_REF { ExpDataRef () (getTransSpan $1 $3) $1 $3 }-| PART_REF { $1 }--PART_REFS :: { [ Expression A0 ] }-: PART_REFS ',' PART_REF { $3 : $1 }-| PART_REF { [ $1 ] }--PART_REF :: { Expression A0 }-: VARIABLE { $1 }-| VARIABLE '(' ')'- { ExpFunctionCall () (getTransSpan $1 $3) $1 Nothing }-| VARIABLE '(' INDICIES ')'- { ExpSubscript () (getTransSpan $1 $4) $1 (fromReverseList $3) }-| VARIABLE '(' INDICIES ')' '(' INDICIES ')'- { let innerSub = ExpSubscript () (getTransSpan $1 $4) $1 (fromReverseList $3)- in ExpSubscript () (getTransSpan $1 $7) innerSub (fromReverseList $6) }--INDICIES :: { [ Index A0 ] }-: INDICIES ',' INDEX { $3 : $1 }-| INDEX { [ $1 ] }--INDEX :: { Index A0 }-: RANGE { $1 }-| RANGE ':' EXPRESSION- { let IxRange () s lower upper _ = $1- in IxRange () (getTransSpan s $3) lower upper (Just $3) }-| EXPRESSION { IxSingle () (getSpan $1) Nothing $1 }--- Following is only as an intermediate stage before having been turned into--- an argument by later transformation.-| id '=' EXPRESSION- { let TId s id = $1 in IxSingle () (getTransSpan $1 s) (Just id) $3 }--RANGE :: { Index A0 }-: ':' { IxRange () (getSpan $1) Nothing Nothing Nothing }-| ':' EXPRESSION { IxRange () (getTransSpan $1 $2) Nothing (Just $2) Nothing }-| EXPRESSION ':' { IxRange () (getTransSpan $1 $2) (Just $1) Nothing Nothing }-| EXPRESSION ':' EXPRESSION- { IxRange () (getTransSpan $1 $3) (Just $1) (Just $3) Nothing }--DO_SPECIFICATION :: { DoSpecification A0 }-: EXPRESSION_ASSIGNMENT_STATEMENT ',' EXPRESSION ',' EXPRESSION- { DoSpecification () (getTransSpan $1 $5) $1 $3 (Just $5) }-| EXPRESSION_ASSIGNMENT_STATEMENT ',' EXPRESSION- { DoSpecification () (getTransSpan $1 $3) $1 $3 Nothing }--IMPLIED_DO :: { Expression A0 }-: '(' EXPRESSION ',' DO_SPECIFICATION ')'- { let expList = AList () (getSpan $2) [ $2 ]- in ExpImpliedDo () (getTransSpan $1 $5) expList $4 }-| '(' EXPRESSION ',' EXPRESSION ',' DO_SPECIFICATION ')'- { let expList = AList () (getTransSpan $2 $4) [ $2, $4 ]- in ExpImpliedDo () (getTransSpan $1 $5) expList $6 }-| '(' EXPRESSION ',' EXPRESSION ',' EXPRESSION_LIST ',' DO_SPECIFICATION ')'- { let { exps = reverse $6;- expList = AList () (getTransSpan $2 exps) ($2 : $4 : reverse $6) }- in ExpImpliedDo () (getTransSpan $1 $9) expList $8 }--FORALL :: { Statement A0 }-: id ':' forall FORALL_HEADER {- let (TId s1 id) = $1 in- let (h,s2) = $4 in- StForall () (getTransSpan s1 s2) (Just id) h-}-| forall FORALL_HEADER {- let (h,s) = $2 in- StForall () (getTransSpan $1 s) Nothing h-}-| forall FORALL_HEADER FORALL_ASSIGNMENT_STMT {- let (h,_) = $2 in- StForallStatement () (getTransSpan $1 $3) h $3-}--FORALL_HEADER :: { (ForallHeader A0, SrcSpan) }--- Standard simple forall header-: '(' FORALL_TRIPLET_SPEC ')' { (ForallHeader [$2] Nothing, getTransSpan $1 $3) }--- forall header with scale expression-| '(' '(' FORALL_TRIPLET_SPEC ')' ',' EXPRESSION ')'- { (ForallHeader [$3] (Just $6), getTransSpan $1 $7) }--- multi forall header-| '(' FORALL_TRIPLET_SPEC_LIST_PLUS_STRIDE ')'- { (ForallHeader $2 Nothing, getTransSpan $1 $3) }--- multi forall header with scale-| '(' FORALL_TRIPLET_SPEC_LIST_PLUS_STRIDE ',' EXPRESSION ')'- { (ForallHeader $2 (Just $4), getTransSpan $1 $5) }--FORALL_TRIPLET_SPEC_LIST_PLUS_STRIDE- :: { [(Name, Expression A0, Expression A0, Maybe (Expression A0))] }-: '(' FORALL_TRIPLET_SPEC ')' ',' FORALL_TRIPLET_SPEC_LIST_PLUS_STRIDE { $2 : $5 }-| {- empty -} { [] }--FORALL_TRIPLET_SPEC :: { (Name, Expression A0, Expression A0, Maybe (Expression A0)) }-: NAME '=' EXPRESSION ':' EXPRESSION { ($1, $3, $5, Nothing) }-| NAME '=' EXPRESSION ':' EXPRESSION ',' EXPRESSION { ($1, $3, $5, Just $7) }--FORALL_ASSIGNMENT_STMT :: { Statement A0 }-: EXPRESSION_ASSIGNMENT_STATEMENT { $1 }-| POINTER_ASSIGNMENT_STMT { $1 }--POINTER_ASSIGNMENT_STMT :: { Statement A0 }-: DATA_REF '=>' EXPRESSION { StPointerAssign () (getTransSpan $1 $3) $1 $3 }--END_FORALL :: { Statement A0 }-: endforall { StEndForall () (getSpan $1) Nothing }-| endforall id { let (TId s id) = $2 in StEndForall () (getTransSpan $1 s) (Just id)}--EXPRESSION_LIST :: { [ Expression A0 ] }-: EXPRESSION_LIST ',' EXPRESSION { $3 : $1 }-| EXPRESSION { [ $1 ] }--ARITHMETIC_SIGN :: { (SrcSpan, UnaryOp) }-: '-' { (getSpan $1, Minus) }-| '+' { (getSpan $1, Plus) }--RELATIONAL_OPERATOR :: { BinaryOp }-: '==' { EQ }-| '!=' { NE }-| '>' { GT }-| '>=' { GTE }-| '<' { LT }-| '<=' { LTE }--VARIABLE :: { Expression A0 }-: id { ExpValue () (getSpan $1) $ let (TId _ s) = $1 in ValVariable s }--NUMERIC_LITERAL :: { Expression A0 }-: INTEGER_LITERAL { $1 } | REAL_LITERAL { $1 }--INTEGERS :: { [ Expression A0 ] }-: INTEGERS ',' INTEGER_LITERAL { $3 : $1 }-| INTEGER_LITERAL { [ $1 ] }--INTEGER_LITERAL :: { Expression A0 }-: int- { let TIntegerLiteral s i = $1- in ExpValue () s $ ValInteger i Nothing }-| int '_' KIND_PARAM- { let TIntegerLiteral s i = $1- in ExpValue () s $ ValInteger i (Just $3) }-| boz { let TBozLiteral s b = $1 in ExpValue () s $ ValBoz b }--REAL_LITERAL :: { Expression A0 }-: float- { let TRealLiteral s r = $1- in ExpValue () s $ ValReal r Nothing }-| float '_' KIND_PARAM- { let TRealLiteral s r = $1- in ExpValue () s $ ValReal r (Just $3) }--LOGICAL_LITERAL :: { Expression A0 }-: bool- { let TLogicalLiteral s b = $1- in ExpValue () s (ValLogical b Nothing) }-| bool '_' KIND_PARAM- { let TLogicalLiteral s b = $1- in ExpValue () s (ValLogical b (Just $3)) }--KIND_PARAM :: { Expression A0 }-: INTEGER_LITERAL { $1 }-| VARIABLE { $1 }--STRING :: { Expression A0 }-: string { let TString s c = $1 in ExpValue () s $ ValString c }--cDATA :: { () } : {% pushContext ConData }-cIMPLICIT :: { () } : {% pushContext ConImplicit }-cNAMELIST :: { () } : {% pushContext ConNamelist }-cCOMMON :: { () } : {% pushContext ConCommon }-cPOP :: { () } : {% popContext }--{--unitNameCheck :: Token -> String -> Parse AlexInput Token ()-unitNameCheck (TId _ name1) name2- | name1 == name2 = return ()- | otherwise = fail "Unit name does not match the corresponding END statement."-unitNameCheck _ _ = return ()--parse = runParse programParser-defTransforms = defaultTransformations Fortran2003--fortran2003Parser- :: B.ByteString -> String -> ParseResult AlexInput Token (ProgramFile A0)-fortran2003Parser = fortran2003ParserWithTransforms defTransforms--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 = 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- parseState = initParseState sourceCode Fortran2003 filename--parseError :: Token -> LexAction a-parseError token = do- parseState <- get-#ifdef DEBUG- tokens <- reverse <$> aiPreviousTokensInLine <$> getAlex-#endif- fail $ psFilename parseState ++ ": parsing failed. "- ++ specifics token-#ifdef DEBUG- ++ '\n' : show tokens-#endif- where specifics (TPause _) = "\nPAUSE statements are not supported in Fortran 2003 or later. "- specifics (TAssign _) = "\nASSIGN statements are not supported in Fortran 2003 or later. "- specifics _ = ""--}
− src/Language/Fortran/Parser/Fortran66.y
@@ -1,512 +0,0 @@--- -*- Mode: Haskell -*---- vim: ft=haskell-{-module Language.Fortran.Parser.Fortran66 ( expressionParser- , statementParser- , fortran66Parser- , fortran66ParserWithTransforms- , fortran66ParserWithModFiles- , fortran66ParserWithModFilesWithTransforms- ) where--import Prelude hiding (EQ,LT,GT) -- Same constructors exist in the AST--import Control.Monad.State-import Data.Maybe (isNothing, fromJust)-import qualified Data.ByteString.Char8 as B-import Language.Fortran.Util.Position-import Language.Fortran.Util.ModFile-import Language.Fortran.ParserMonad-import Language.Fortran.Lexer.FixedForm-import Language.Fortran.Lexer.FixedForm.Utils-import Language.Fortran.Transformer-import Language.Fortran.AST-import Language.Fortran.AST.RealLit--}--%name programParser PROGRAM-%name statementParser STATEMENT-%name expressionParser EXPRESSION-%monad { LexAction }-%lexer { lexer } { TEOF _ }-%tokentype { Token }-%error { parseError }--%token- '(' { TLeftPar _ }- ')' { TRightPar _ }- ',' { TComma _ }- '.' { TDot _ }- function { TFunction _ }- subroutine { TSubroutine _ }- blockData { TBlockData _ }- end { TEnd _ }- '=' { TOpAssign _ }- assign { TAssign _ }- to { TTo _ }- goto { TGoto _ }- if { TIf _ }- call { TCall _ }- return { TReturn _ }- continue { TContinue _ }- stop { TStop _ }- pause { TPause _ }- do { TDo _ }- read { TRead _ }- write { TWrite _ }- rewind { TRewind _ }- backspace { TBackspace _ }- endfile { TEndfile _ }- common { TCommon _ }- equivalence { TEquivalence _ }- external { TExternal _ }- dimension { TDimension _ }- integer { TType _ "integer" }- real { TType _ "real" }- doublePrecision { TType _ "doubleprecision" }- logical { TType _ "logical" }- complex { TType _ "complex" }- data { TData _ }- format { TFormat _ }- blob { TBlob _ _ }- int { TInt _ _ }- exponent { TExponent _ _ }- bool { TBool _ _ }- '+' { TOpPlus _ }- '-' { TOpMinus _ }- '**' { TOpExp _ }- '*' { TStar _ }- '/' { TSlash _ }- or { TOpOr _ }- and { TOpAnd _ }- not { TOpNot _ }- '<' { TOpLT _ }- '<=' { TOpLE _ }- '>' { TOpGT _ }- '>=' { TOpGE _ }- '==' { TOpEQ _ }- '!=' { TOpNE _ }- id { TId _ _ }- comment { TComment _ _ }- hollerith { THollerith _ _ }- label { TLabel _ _ }- newline { TNewline _ }--%left or-%left and-%right not--%nonassoc '>' '<' '>=' '<=' '==' '!='-%nonassoc RELATIONAL--%left '+' '-'-%left '*' '/'-%right NEGATION-%right '**'--%%---- This rule is to ignore leading whitespace-PROGRAM :: { ProgramFile A0 }-: NEWLINE PROGRAM_INNER { $2 }-| PROGRAM_INNER { $1 }--PROGRAM_INNER :: { ProgramFile A0 }-: PROGRAM_UNITS BLOCKS { ProgramFile (MetaInfo { miVersion = Fortran66, miFilename = "" }) (reverse $1 ++ convCmts (reverse $2)) }-| {- empty -} { ProgramFile (MetaInfo { miVersion = Fortran66, miFilename = "" }) [] }--PROGRAM_UNITS :: { [ ProgramUnit A0 ] }-: PROGRAM_UNITS MAIN_PROGRAM_UNIT { $2 : $1 }-| PROGRAM_UNITS BLOCKS OTHER_PROGRAM_UNIT { convCmts (reverse $2) ++ ($3 : $1) }-| MAIN_PROGRAM_UNIT { [ $1 ] }-| BLOCKS OTHER_PROGRAM_UNIT { convCmts (reverse $1) ++ [ $2 ] }--MAIN_PROGRAM_UNIT :: { ProgramUnit A0 }-: BLOCKS end MAYBE_NEWLINE- { let blocks = reverse $1- in PUMain () (getTransSpan $1 $2) Nothing blocks Nothing }--OTHER_PROGRAM_UNIT :: { ProgramUnit A0 }-: TYPE_SPEC function NAME MAYBE_ARGUMENTS NEWLINE BLOCKS end MAYBE_NEWLINE- { PUFunction () (getTransSpan $1 $7) (Just $1) emptyPrefixSuffix $3 $4 Nothing (reverse $6) Nothing }-| function NAME MAYBE_ARGUMENTS NEWLINE BLOCKS end MAYBE_NEWLINE- { PUFunction () (getTransSpan $1 $6) Nothing emptyPrefixSuffix $2 $3 Nothing (reverse $5) Nothing }-| subroutine NAME MAYBE_ARGUMENTS NEWLINE BLOCKS end MAYBE_NEWLINE- { PUSubroutine () (getTransSpan $1 $6) emptyPrefixSuffix $2 $3 (reverse $5) Nothing }-| blockData NEWLINE BLOCKS end MAYBE_NEWLINE { PUBlockData () (getTransSpan $1 $4) Nothing (reverse $3) }--MAYBE_ARGUMENTS :: { Maybe (AList Expression A0) }-: '(' MAYBE_VARIABLES ')' { $2 }-| {- Nothing -} { Nothing }--NAME :: { Name } : id { let (TId _ name) = $1 in name }--BLOCKS :: { [ Block A0 ] }-: BLOCKS BLOCK { $2 : $1 }-| {- EMPTY -} { [ ] }--BLOCK :: { Block A0 }-: LABEL_IN_6COLUMN STATEMENT NEWLINE { BlStatement () (getTransSpan $1 $2) (Just $1) $2 }-| STATEMENT NEWLINE { BlStatement () (getSpan $1) Nothing $1 }-| comment NEWLINE { let (TComment s c) = $1 in BlComment () s (Comment c) }--MAYBE_NEWLINE :: { Maybe Token }-: NEWLINE { Just $1 }-| {- EMPTY -} { Nothing }--NEWLINE :: { Token }-: NEWLINE newline { $1 }-| newline { $1 }--STATEMENT :: { Statement A0 }-: LOGICAL_IF_STATEMENT { $1 }-| DO_STATEMENT { $1 }-| OTHER_EXECUTABLE_STATEMENT { $1 }-| NONEXECUTABLE_STATEMENT { $1 }--LOGICAL_IF_STATEMENT :: { Statement A0 }-: if '(' EXPRESSION ')' OTHER_EXECUTABLE_STATEMENT- { StIfLogical () (getTransSpan $1 $5) $3 $5 }--DO_STATEMENT :: { Statement A0 }-: do LABEL_IN_STATEMENT DO_SPECIFICATION- { StDo () (getTransSpan $1 $3) Nothing (Just $2) (Just $3) }--DO_SPECIFICATION :: { DoSpecification A0 }-: EXPRESSION_ASSIGNMENT_STATEMENT ',' INT_OR_VAR ',' INT_OR_VAR- { DoSpecification () (getTransSpan $1 $5) $1 $3 (Just $5) }-| EXPRESSION_ASSIGNMENT_STATEMENT ',' INT_OR_VAR- { DoSpecification () (getTransSpan $1 $3) $1 $3 Nothing }--INT_OR_VAR :: { Expression A0 }-: INTEGER_LITERAL { $1 }-| VARIABLE { $1 }--OTHER_EXECUTABLE_STATEMENT :: { Statement A0 }-: EXPRESSION_ASSIGNMENT_STATEMENT { $1 }-| assign LABEL_IN_STATEMENT to VARIABLE { StLabelAssign () (getTransSpan $1 $4) $2 $4 }-| goto LABEL_IN_STATEMENT { StGotoUnconditional () (getTransSpan $1 $2) $2 }-| goto VARIABLE LABELS_IN_STATEMENT { StGotoAssigned () (getTransSpan $1 $3) $2 (Just $3) }-| goto LABELS_IN_STATEMENT VARIABLE { StGotoComputed () (getTransSpan $1 $3) $2 $3 }-| if '(' EXPRESSION ')' LABEL_IN_STATEMENT ',' LABEL_IN_STATEMENT ',' LABEL_IN_STATEMENT { StIfArithmetic () (getTransSpan $1 $9) $3 $5 $7 $9 }-| call VARIABLE ARGUMENTS- { StCall () (getTransSpan $1 $3) $2 (Just $3) }-| call VARIABLE { StCall () (getTransSpan $1 $2) $2 Nothing }-| return { StReturn () (getSpan $1) Nothing }-| continue { StContinue () $ getSpan $1 }-| stop INTEGER_LITERAL { StStop () (getTransSpan $1 $2) $ Just $2 }-| stop { StStop () (getSpan $1) Nothing }-| pause INTEGER_LITERAL { StPause () (getTransSpan $1 $2) $ Just $2 }-| pause { StPause () (getSpan $1) Nothing }-| rewind UNIT { StRewind2 () (getTransSpan $1 $2) $2 }-| backspace UNIT { StBackspace2 () (getTransSpan $1 $2) $2 }-| endfile UNIT { StEndfile2 () (getTransSpan $1 $2) $2 }-| write READ_WRITE_ARGUMENTS { let (cilist, iolist) = $2 in StWrite () (getTransSpan $1 $2) cilist iolist }-| read READ_WRITE_ARGUMENTS { let (cilist, iolist) = $2 in StRead () (getTransSpan $1 $2) cilist iolist }--EXPRESSION_ASSIGNMENT_STATEMENT :: { Statement A0 }-: ELEMENT '=' EXPRESSION { StExpressionAssign () (getTransSpan $1 $3) $1 $3 }--NONEXECUTABLE_STATEMENT :: { Statement A0 }-: external FUNCTION_NAMES { StExternal () (getTransSpan $1 $2) (aReverse $2) }-| dimension ARRAY_DECLARATORS { StDimension () (getTransSpan $1 $2) (aReverse $2) }-| common COMMON_GROUPS { StCommon () (getTransSpan $1 $2) (aReverse $2) }-| equivalence EQUIVALENCE_GROUPS { StEquivalence () (getTransSpan $1 $2) (aReverse $2) }-| data DATA_GROUPS { StData () (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- { let TBlob s blob = $2 in StFormatBogus () (getTransSpan $1 s) blob }-| TYPE_SPEC DECLARATORS { StDeclaration () (getTransSpan $1 $2) $1 Nothing (aReverse $2) }--READ_WRITE_ARGUMENTS :: { (AList ControlPair A0, Maybe (AList Expression A0)) }-: '(' UNIT ')' IO_ELEMENTS { (AList () (getSpan $2) [ ControlPair () (getSpan $2) Nothing $2 ], Just (aReverse $4)) }-| '(' UNIT ',' FORM ')' IO_ELEMENTS { (AList () (getTransSpan $2 $4) [ ControlPair () (getSpan $2) Nothing $2, ControlPair () (getSpan $4) Nothing $4 ], Just (aReverse $6)) }-| '(' UNIT ')' { (AList () (getSpan $2) [ ControlPair () (getSpan $2) Nothing $2 ], Nothing) }-| '(' UNIT ',' FORM ')' { (AList () (getTransSpan $2 $4) [ ControlPair () (getSpan $2) Nothing $2, ControlPair () (getSpan $4) Nothing $4 ], Nothing) }---- Not my terminology a VAR or an INT (probably positive) is defined as UNIT.-UNIT :: { Expression A0 }-: INTEGER_LITERAL { $1 }-| VARIABLE { $1 }--FORM :: { Expression A0 }-: VARIABLE { $1 }-| LABEL_IN_STATEMENT { $1 }--IO_ELEMENTS :: { AList Expression A0 }-: IO_ELEMENTS ',' IO_ELEMENT { setSpan (getTransSpan $1 $3) $ $3 `aCons` $1}-| IO_ELEMENT { AList () (getSpan $1) [ $1 ] }--IO_ELEMENT :: { Expression A0 }-: VARIABLE { $1 }--- There should also be a caluse for variable names but not way to--- differentiate it at this stage from VARIABLE. Hence, it is omitted to prevent--- reduce/reduce conflict.-| SUBSCRIPT { $1 }-| '(' IO_ELEMENTS ',' DO_SPECIFICATION ')' { ExpImpliedDo () (getTransSpan $1 $5) $2 $4 }--ELEMENT :: { Expression A0 }-: VARIABLE { $1 }-| SUBSCRIPT { $1 }--DATA_GROUPS :: { AList DataGroup A0 }-: DATA_GROUPS ',' NAME_LIST '/' DATA_ITEMS '/' { setSpan (getTransSpan $1 $6) $ (DataGroup () (getTransSpan $3 $6) (aReverse $3) (aReverse $5)) `aCons` $1 }-| NAME_LIST '/' DATA_ITEMS '/' { AList () (getTransSpan $1 $4) [ DataGroup () (getTransSpan $1 $4) (aReverse $1) (aReverse $3) ] }--DATA_ITEMS :: { AList Expression A0 }-: DATA_ITEMS ',' DATA_ITEM { setSpan (getTransSpan $1 $3) $ $3 `aCons` $1}-| DATA_ITEM { AList () (getSpan $1) [ $1 ] }--DATA_ITEM :: { Expression A0 }-: INTEGER_LITERAL '*' DATA_ITEM_LEVEL1 { ExpBinary () (getTransSpan $1 $3) Multiplication $1 $3 }-| DATA_ITEM_LEVEL1 { $1 }--DATA_ITEM_LEVEL1 :: { Expression A0 }-: SIGNED_NUMERIC_LITERAL { $1 }-| COMPLEX_LITERAL { $1 }-| LOGICAL_LITERAL { $1 }-| HOLLERITH { $1 }--EQUIVALENCE_GROUPS :: { AList (AList Expression) A0 }-: EQUIVALENCE_GROUPS ',' '(' NAME_LIST ')' { setSpan (getTransSpan $1 $5) $ (setSpan (getTransSpan $3 $5) $ aReverse $4) `aCons` $1 }-| '(' NAME_LIST ')' { let s = (getTransSpan $1 $3) in AList () s [ setSpan s $ aReverse $2 ] }--COMMON_GROUPS :: { AList CommonGroup A0 }-: COMMON_GROUPS COMMON_GROUP { setSpan (getTransSpan $1 $2) $ $2 `aCons` $1 }-| INIT_COMMON_GROUP { AList () (getSpan $1) [ $1 ] }--COMMON_GROUP :: { CommonGroup A0 }-: COMMON_NAME DECLARATORS- { CommonGroup () (getTransSpan $1 $2) (Just $1) $ aReverse $2 }-| '/' '/' DECLARATORS { CommonGroup () (getTransSpan $1 $3) Nothing $ aReverse $3 }--INIT_COMMON_GROUP :: { CommonGroup A0 }-: COMMON_NAME DECLARATORS- { CommonGroup () (getTransSpan $1 $2) (Just $1) $ aReverse $2 }-| '/' '/' DECLARATORS { CommonGroup () (getTransSpan $1 $3) Nothing $ aReverse $3 }-| DECLARATORS { CommonGroup () (getSpan $1) Nothing $ aReverse $1 }--COMMON_NAME :: { Expression A0 }-: '/' VARIABLE '/' { setSpan (getTransSpan $1 $3) $2 }--NAME_LIST :: { AList Expression A0 }-: NAME_LIST ',' NAME_LIST_ELEMENT { setSpan (getTransSpan $1 $3) $ $3 `aCons` $1 }-| NAME_LIST_ELEMENT { AList () (getSpan $1) [ $1 ] }--NAME_LIST_ELEMENT :: { Expression A0 }-: VARIABLE { $1 }-| SUBSCRIPT { $1 }---- Note that declarator lists in the F66 parser don't have initializers.-DECLARATORS :: { AList Declarator A0 }-: DECLARATORS ',' DECLARATOR { setSpan (getTransSpan $1 $3) $ $3 `aCons` $1 }-| DECLARATOR { AList () (getSpan $1) [ $1 ] }--DECLARATOR :: { Declarator A0 }-: ARRAY_DECLARATOR { $1 }-| VARIABLE_DECLARATOR { $1 }--ARRAY_DECLARATORS :: { AList Declarator A0 }-: ARRAY_DECLARATORS ',' ARRAY_DECLARATOR- { setSpan (getTransSpan $1 $3) $ $3 `aCons` $1 }-| ARRAY_DECLARATOR- { AList () (getSpan $1) [ $1 ] }--ARRAY_DECLARATOR :: { Declarator A0 }-: VARIABLE '(' DIMENSION_DECLARATORS ')'- { Declarator () (getTransSpan $1 $4) $1 (ArrayDecl (aReverse $3)) Nothing Nothing }--DIMENSION_DECLARATORS :: { AList DimensionDeclarator A0 }-: DIMENSION_DECLARATORS ',' DIMENSION_DECLARATOR- { setSpan (getTransSpan $1 $3) $ $3 `aCons` $1 }-| DIMENSION_DECLARATOR- { AList () (getSpan $1) [ $1 ] }--DIMENSION_DECLARATOR :: { DimensionDeclarator A0 }-: EXPRESSION { DimensionDeclarator () (getSpan $1) Nothing (Just $1) }--VARIABLE_DECLARATOR :: { Declarator A0 }-: VARIABLE { Declarator () (getSpan $1) $1 ScalarDecl Nothing Nothing }---- Here the procedure should be either a function or subroutine name, but--- since they are syntactically identical at this stage subroutine names--- are also emitted as function names.-FUNCTION_NAMES :: { AList Expression A0 }-: FUNCTION_NAMES ',' VARIABLE { setSpan (getTransSpan $1 $3) $ $3 `aCons` $1 }-| VARIABLE { AList () (getSpan $1) [ $1 ] }--ARGUMENTS :: { AList Argument A0 }-: ARGUMENTS_LEVEL1 ')' { setSpan (getTransSpan $1 $2) $ aReverse $1 }--ARGUMENTS_LEVEL1 :: { AList Argument A0 }-: ARGUMENTS_LEVEL1 ',' CALLABLE_EXPRESSION { setSpan (getTransSpan $1 $3) $ $3 `aCons` $1 }-| '(' CALLABLE_EXPRESSION { AList () (getTransSpan $1 $2) [ $2 ] }-| '(' { AList () (getSpan $1) [ ] }---- Expression all by itself subsumes all other callable expressions.-CALLABLE_EXPRESSION :: { Argument A0 }-: HOLLERITH { Argument () (getSpan $1) Nothing $1 }-| EXPRESSION { Argument () (getSpan $1) Nothing $1 }--EXPRESSION :: { Expression A0 }-: EXPRESSION '+' EXPRESSION { ExpBinary () (getTransSpan $1 $3) Addition $1 $3 }-| EXPRESSION '-' EXPRESSION { ExpBinary () (getTransSpan $1 $3) Subtraction $1 $3 }-| EXPRESSION '*' EXPRESSION { ExpBinary () (getTransSpan $1 $3) Multiplication $1 $3 }-| EXPRESSION '/' EXPRESSION { ExpBinary () (getTransSpan $1 $3) Division $1 $3 }-| EXPRESSION '**' EXPRESSION { ExpBinary () (getTransSpan $1 $3) Exponentiation $1 $3 }-| ARITHMETIC_SIGN EXPRESSION %prec NEGATION { ExpUnary () (getTransSpan (fst $1) $2) (snd $1) $2 }-| EXPRESSION or EXPRESSION { ExpBinary () (getTransSpan $1 $3) Or $1 $3 }-| EXPRESSION and EXPRESSION { ExpBinary () (getTransSpan $1 $3) And $1 $3 }-| not EXPRESSION { ExpUnary () (getTransSpan $1 $2) Not $2 }-| EXPRESSION RELATIONAL_OPERATOR EXPRESSION %prec RELATIONAL { ExpBinary () (getTransSpan $1 $3) $2 $1 $3 }-| '(' EXPRESSION ')' { setSpan (getTransSpan $1 $3) $2 }-| INTEGER_LITERAL { $1 }-| REAL_LITERAL { $1 }-| COMPLEX_LITERAL { $1 }-| LOGICAL_LITERAL { $1 }-| SUBSCRIPT { $1 }--- There should be FUNCTION_CALL here but as far as the parser is concerned it is same as SUBSCRIPT,--- hence putting it here would cause a reduce/reduce conflict.-| VARIABLE { $1 }--RELATIONAL_OPERATOR :: { BinaryOp }-: '==' { EQ }-| '!=' { NE }-| '>' { GT }-| '>=' { GTE }-| '<' { LT }-| '<=' { LTE }--SUBSCRIPT :: { Expression A0 }-: VARIABLE '(' ')'- { ExpFunctionCall () (getTransSpan $1 $3) $1 Nothing }-| VARIABLE '(' INDICIES ')'- { ExpSubscript () (getTransSpan $1 $4) $1 (fromReverseList $3) }--INDICIES :: { [ Index A0 ] }-: INDICIES ',' EXPRESSION { IxSingle () (getSpan $3) Nothing $3 : $1 }-| EXPRESSION { [ IxSingle () (getSpan $1) Nothing $1 ] }--ARITHMETIC_SIGN :: { (SrcSpan, UnaryOp) }-: '-' { (getSpan $1, Minus) }-| '+' { (getSpan $1, Plus) }--MAYBE_VARIABLES :: { Maybe (AList Expression A0) }-: VARIABLES { Just $ fromReverseList $1 } | {- EMPTY -} { Nothing }--VARIABLES :: { [ Expression A0 ] }-: VARIABLES ',' VARIABLE { $3 : $1 } | VARIABLE { [ $1 ] }---- This may also be used to parse a function name, or an array name. Since when--- are valid options in a production there is no way of differentiating them at--- this stage.--- This at least reduces reduce/reduce conflicts.-VARIABLE :: { Expression A0 }-: id { ExpValue () (getSpan $1) $ let (TId _ s) = $1 in ValVariable s }--SIGNED_INTEGER_LITERAL :: { Expression A0 }-: ARITHMETIC_SIGN INTEGER_LITERAL { ExpUnary () (getTransSpan (fst $1) $2) (snd $1) $2 }-| INTEGER_LITERAL { $1 }--INTEGER_LITERAL :: { Expression A0 }-: int { ExpValue () (getSpan $1) $ let (TInt _ i) = $1 in ValInteger i Nothing }--SIGNED_REAL_LITERAL :: { Expression A0 }-: ARITHMETIC_SIGN REAL_LITERAL { ExpUnary () (getTransSpan (fst $1) $2) (snd $1) $2 }-| REAL_LITERAL { $1 }--REAL_LITERAL :: { Expression A0 }-: int EXPONENT { makeReal (Just $1) Nothing Nothing (Just $2) }-| int '.' MAYBE_EXPONENT { makeReal (Just $1) (Just $2) Nothing $3 }-| '.' int MAYBE_EXPONENT { makeReal Nothing (Just $1) (Just $2) $3 }-| int '.' int MAYBE_EXPONENT { makeReal (Just $1) (Just $2) (Just $3) $4 }--MAYBE_EXPONENT :: { Maybe (SrcSpan, String) }-: EXPONENT { Just $1 }-| {-EMPTY-} { Nothing }--EXPONENT :: { (SrcSpan, String) }-: exponent { let (TExponent s exp) = $1 in (s, exp) }--SIGNED_NUMERIC_LITERAL :: { Expression A0 }-: SIGNED_INTEGER_LITERAL { $1 }-| SIGNED_REAL_LITERAL { $1 }--COMPLEX_LITERAL :: { Expression A0 }-: '(' SIGNED_NUMERIC_LITERAL ',' SIGNED_NUMERIC_LITERAL ')' { ExpValue () (getTransSpan $1 $5) (ValComplex $2 $4)}--LOGICAL_LITERAL :: { Expression A0 }-: bool { let TBool s b = $1 in ExpValue () s $ ValLogical b Nothing }--HOLLERITH :: { Expression A0 }-: hollerith { ExpValue () (getSpan $1) $ let (THollerith _ h) = $1 in ValHollerith h }--LABELS_IN_STATEMENT :: { AList Expression A0 }-: LABELS_IN_STATEMENT_LEVEL1 ')' { setSpan (getTransSpan $1 $2) $ aReverse $1 }--LABELS_IN_STATEMENT_LEVEL1 :: { AList Expression A0 }-: LABELS_IN_STATEMENT_LEVEL1 ',' LABEL_IN_STATEMENT { setSpan (getTransSpan $1 $3) $ $3 `aCons` $1 }-| '(' LABEL_IN_STATEMENT { AList () (getTransSpan $1 $2) [ $2 ] }---- Labels that occur in the first 6 columns-LABEL_IN_6COLUMN :: { Expression A0 }-: label { ExpValue () (getSpan $1) (let (TLabel _ l) = $1 in ValInteger l Nothing) }---- Labels that occur in statements-LABEL_IN_STATEMENT :: { Expression A0 }-: int { ExpValue () (getSpan $1) (let (TInt _ l) = $1 in ValInteger l Nothing) }--TYPE_SPEC :: { TypeSpec A0 }-: integer { TypeSpec () (getSpan $1) TypeInteger Nothing }-| real { TypeSpec () (getSpan $1) TypeReal Nothing }-| doublePrecision { TypeSpec () (getSpan $1) TypeDoublePrecision Nothing }-| logical { TypeSpec () (getSpan $1) TypeLogical Nothing }-| complex { TypeSpec () (getSpan $1) TypeComplex Nothing }--{--parse = runParse programParser-defTransforms = defaultTransformations Fortran66--fortran66Parser- :: B.ByteString -> String -> ParseResult AlexInput Token (ProgramFile A0)-fortran66Parser = fortran66ParserWithTransforms defTransforms--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- parseState = initParseState sourceCode Fortran66 filename--parseError :: Token -> LexAction a-parseError _ = do- parseState <- get-#ifdef DEBUG- tokens <- reverse <$> aiPreviousTokensInLine <$> getAlex-#endif- fail $ psFilename parseState ++ ": parsing failed. "-#ifdef DEBUG- ++ '\n' : show tokens-#endif--convCmts = map convCmt-convCmt (BlComment a s c) = PUComment a s c-convCmt _ = error "convCmt applied to something that is not a comment"--}
− src/Language/Fortran/Parser/Fortran77.y
@@ -1,1152 +0,0 @@--- -*- Mode: Haskell -*---- vim: ft=haskell-{-{-# LANGUAGE TupleSections #-}-module Language.Fortran.Parser.Fortran77- ( expressionParser- , statementParser- , blockParser- , fortran77Parser- , 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--import Control.Monad.State-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-import Language.Fortran.Lexer.FixedForm hiding (Move(..))-import Language.Fortran.Lexer.FixedForm.Utils-import Language.Fortran.Transformer-import Language.Fortran.AST-import Language.Fortran.AST.RealLit--import Data.Generics.Uniplate.Operations-import System.Directory-import System.FilePath-import Control.Exception--}--%name programParser PROGRAM-%name includesParser INCLUDES-%name blockParser BLOCK-%name statementParser STATEMENT-%name expressionParser EXPRESSION-%monad { LexAction }-%lexer { lexer } { TEOF _ }-%tokentype { Token }-%error { parseError }--%token- '(' { TLeftPar _ }- ')' { TRightPar _ }- '(/' { TLeftArrayPar _ }- '/)' { TRightArrayPar _ }- ',' { TComma _ }- '.' { TDot _ }- '%' { TPercent _ }- ':' { TColon _ }- include { TInclude _ }- program { TProgram _ }- function { TFunction _ }- subroutine { TSubroutine _ }- endprogram { TEndProgram _ }- endfunction { TEndFunction _ }- endsubroutine { TEndSubroutine _ }- blockData { TBlockData _ }- structure { TStructure _ }- union { TUnion _ }- map { TMap _ }- endstructure { TEndStructure _ }- endunion { TEndUnion _ }- endmap { TEndMap _ }- record { TRecord _ }- end { TEnd _ }- '=' { TOpAssign _ }- assign { TAssign _ }- to { TTo _ }- goto { TGoto _ }- if { TIf _ }- then { TThen _ }- else { TElse _ }- elsif { TElsif _ }- endif { TEndif _ }- call { TCall _ }- return { TReturn _ }- save { TSave _ }- continue { TContinue _ }- stop { TStop _ }- exit { TExit _ }- cycle { TCycle _ }- case { TCase _ }- selectcase { TSelectCase _ }- endselect { TEndSelect _ }- casedefault { TCaseDefault _ }- pause { TPause _ }- do { TDo _ }- doWhile { TDoWhile _ }- while { TWhile _ }- enddo { TEndDo _ }- read { TRead _ }- write { TWrite _ }- print { TPrint _ }- typeprint { TTypePrint _ }- open { TOpen _ }- close { TClose _ }- inquire { TInquire _ }- rewind { TRewind _ }- backspace { TBackspace _ }- endfile { TEndfile _ }- common { TCommon _ }- equivalence { TEquivalence _ }- external { TExternal _ }- dimension { TDimension _ }- byte { TType _ "byte" }- character { TType _ "character" }- integer { TType _ "integer" }- real { TType _ "real" }- doublePrecision { TType _ "doubleprecision" }- logical { TType _ "logical" }- complex { TType _ "complex" }- doubleComplex { TType _ "doublecomplex" }- intrinsic { TIntrinsic _ }- implicit { TImplicit _ }- parameter { TParameter _ }- pointer { TPointer _ }- entry { TEntry _ }- none { TNone _ }- data { TData _ }- automatic { TAutomatic _ }- static { TStatic _ }- format { TFormat _ }- blob { TBlob _ _ }- int { TInt _ _ }- boz { TBozLiteral _ _ }- exponent { TExponent _ _ }- bool { TBool _ _ }- '+' { TOpPlus _ }- '-' { TOpMinus _ }- '**' { TOpExp _ }- '*' { TStar _ }- '/' { TSlash _ }- '&' { TAmpersand _ }- eqv { TOpEquivalent _ }- neqv { TOpNotEquivalent _ }- or { TOpOr _ }- and { TOpAnd _ }- xor { TOpXOr _ }- not { TOpNot _ }- '<' { TOpLT _ }- '<=' { TOpLE _ }- '>' { TOpGT _ }- '>=' { TOpGE _ }- '==' { TOpEQ _ }- '!=' { TOpNE _ }- id { TId _ _ }- comment { TComment _ _ }- hollerith { THollerith _ _ }- string { TString _ _ }- label { TLabel _ _ }- newline { TNewline _ }--%left eqv neqv xor-%left or-%left and-%right not--%nonassoc '>' '<' '>=' '<=' '==' '!='-%nonassoc RELATIONAL--%left CONCAT--%left '+' '-'-%left '*' '/'-%right NEGATION-%right '**'--%%--maybe(p)-: p { Just $1 }-| {- empty -} { Nothing }--rev_list1(p)-: p { [$1] }-| rev_list1(p) p { $2 : $1 }--rev_list(p)-: rev_list1(p) { $1 }-| {- empty -} { [] }--list1(p)-: rev_list1(p) { reverse $1 }--list(p)-: rev_list(p) { reverse $1 }---- This rule is to ignore leading whitespace-PROGRAM :: { ProgramFile A0 }-: NEWLINE PROGRAM_INNER { $2 }-| PROGRAM_INNER { $1 }--PROGRAM_INNER :: { ProgramFile A0 }-: PROGRAM_UNITS { ProgramFile (MetaInfo { miVersion = Fortran77, miFilename = "" }) (reverse $1) }-| {- empty -} { ProgramFile (MetaInfo { miVersion = Fortran77, miFilename = "" }) [] }--PROGRAM_UNITS :: { [ ProgramUnit A0 ] }-: PROGRAM_UNITS maybe(LABEL_IN_6COLUMN) PROGRAM_UNIT maybe(NEWLINE) { $3 : $1 }-| maybe(LABEL_IN_6COLUMN) PROGRAM_UNIT maybe(NEWLINE) { [ $2 ] }--PROGRAM_UNIT :: { ProgramUnit A0 }-: program NAME NEWLINE BLOCKS ENDPROG- { PUMain () (getTransSpan $1 $5) (Just $2) (reverse $4) Nothing }-| TYPE_SPEC function NAME MAYBE_ARGUMENTS NEWLINE BLOCKS ENDFUN- { PUFunction () (getTransSpan $1 $7) (Just $1) emptyPrefixSuffix $3 $4 Nothing (reverse $6) Nothing }-| function NAME MAYBE_ARGUMENTS NEWLINE BLOCKS ENDFUN- { PUFunction () (getTransSpan $1 $6) Nothing emptyPrefixSuffix $2 $3 Nothing (reverse $5) Nothing }-| subroutine NAME MAYBE_ARGUMENTS NEWLINE BLOCKS ENDSUB- { PUSubroutine () (getTransSpan $1 $6) emptyPrefixSuffix $2 $3 (reverse $5) Nothing }-| blockData NEWLINE BLOCKS END { PUBlockData () (getTransSpan $1 $4) Nothing (reverse $3) }-| blockData NAME NEWLINE BLOCKS END { PUBlockData () (getTransSpan $1 $5) (Just $2) (reverse $4) }-| comment { let (TComment s c) = $1 in PUComment () s (Comment c) }--END :: { Token }-: end { $1 }-| LABEL_IN_6COLUMN end { $2 }--ENDPROG :: { Token }-: END { $1 }-| endprogram MAYBE_ID { $1 }-| LABEL_IN_6COLUMN endprogram MAYBE_ID { $2 }--ENDFUN :: { Token }-: END { $1 }-| endfunction MAYBE_ID { $1 }-| LABEL_IN_6COLUMN endfunction MAYBE_ID { $2 }--ENDSUB :: { Token }-: END { $1 }-| endsubroutine MAYBE_ID { $1 }-| LABEL_IN_6COLUMN endsubroutine MAYBE_ID { $2 }--MAYBE_ARGUMENTS :: { Maybe (AList Expression A0) }-: '(' MAYBE_VARIABLES ')' { $2 }-| {- Nothing -} { Nothing }--MAYBE_ID :: { Maybe Name }-: id { let (TId _ name) = $1 in Just name }-| {- empty -} { Nothing }--NAME :: { Name } : id { let (TId _ name) = $1 in name }--INCLUDES :: { [ Block A0 ] }-: maybe(NEWLINE) list(BLOCK) { $2 }--BLOCKS :: { [ Block A0 ] }-: BLOCKS BLOCK { $2 : $1 }-| {- EMPTY -} { [ ] }--BLOCK :: { Block A0 }-: IF_BLOCK NEWLINE { $1 }-| LABEL_IN_6COLUMN STATEMENT NEWLINE { BlStatement () (getTransSpan $1 $2) (Just $1) $2 }-| STATEMENT NEWLINE { BlStatement () (getSpan $1) Nothing $1 }-| COMMENT_BLOCK { $1 }--IF_BLOCK :: { Block A0 }-: if '(' EXPRESSION ')' then NEWLINE BLOCKS ELSE_BLOCKS {- let (endSpan, endLabel, conds, blocks) = $8- in BlIf () (getTransSpan $1 endSpan) Nothing Nothing ((Just $3):conds) ((reverse $7):blocks) endLabel- }-| LABEL_IN_6COLUMN if '(' EXPRESSION ')' then NEWLINE BLOCKS ELSE_BLOCKS {- let (endSpan, endLabel, conds, blocks) = $9- in BlIf () (getTransSpan $1 endSpan) (Just $1) Nothing ((Just $4):conds) ((reverse $8):blocks) endLabel- }--ELSE_BLOCKS :: { (SrcSpan, Maybe (Expression A0), [Maybe (Expression A0)], [[Block A0]]) }-: maybe(LABEL_IN_6COLUMN) elsif '(' EXPRESSION ')' then NEWLINE BLOCKS ELSE_BLOCKS- { let (endSpan, endLabel, conds, blocks) = $9- in (endSpan, endLabel, Just $4 : conds, reverse $8 : blocks) }-| maybe(LABEL_IN_6COLUMN) else NEWLINE BLOCKS maybe(LABEL_IN_6COLUMN) endif- { (getSpan $6, $5, [Nothing], [reverse $4]) }-| maybe(LABEL_IN_6COLUMN) endif { (getSpan $2, $1, [], []) }--COMMENT_BLOCK :: { Block A0 }-: comment NEWLINE { let (TComment s c) = $1 in BlComment () s (Comment c) }--NEWLINE :: { Token }-: NEWLINE newline { $1 }-| newline { $1 }--STATEMENT :: { Statement A0 }-: LOGICAL_IF_STATEMENT { $1 }-| DO_STATEMENT { $1 }-| EXECUTABLE_STATEMENT { $1 }-| NONEXECUTABLE_STATEMENT { $1 }--LOGICAL_IF_STATEMENT :: { Statement A0 }-: if '(' EXPRESSION ')' EXECUTABLE_STATEMENT { StIfLogical () (getTransSpan $1 $5) $3 $5 }--DO_STATEMENT :: { Statement A0 }-: do LABEL_IN_STATEMENT DO_SPECIFICATION { StDo () (getTransSpan $1 $3) Nothing (Just $2) (Just $3) }-| do LABEL_IN_STATEMENT ',' DO_SPECIFICATION { StDo () (getTransSpan $1 $4) Nothing (Just $2) (Just $4) }-| do DO_SPECIFICATION { StDo () (getTransSpan $1 $2) Nothing Nothing (Just $2) }-| do { StDo () (getSpan $1) Nothing Nothing Nothing }--DO_SPECIFICATION :: { DoSpecification A0 }-: EXPRESSION_ASSIGNMENT_STATEMENT ',' EXPRESSION ',' EXPRESSION { DoSpecification () (getTransSpan $1 $5) $1 $3 (Just $5) }-| EXPRESSION_ASSIGNMENT_STATEMENT ',' EXPRESSION { DoSpecification () (getTransSpan $1 $3) $1 $3 Nothing }--EXECUTABLE_STATEMENT :: { Statement A0 }-: EXPRESSION_ASSIGNMENT_STATEMENT { $1 }-| assign LABEL_IN_STATEMENT to VARIABLE { StLabelAssign () (getTransSpan $1 $4) $2 $4 }-| GOTO_STATEMENT { $1 }-| if '(' EXPRESSION ')' LABEL_IN_STATEMENT ',' LABEL_IN_STATEMENT ',' LABEL_IN_STATEMENT { StIfArithmetic () (getTransSpan $1 $9) $3 $5 $7 $9 }-| doWhile '(' EXPRESSION ')'- { StDoWhile () (getTransSpan $1 $4) Nothing Nothing $3 }-| do LABEL_IN_STATEMENT while '(' EXPRESSION ')'- { StDoWhile () (getTransSpan $1 $6) Nothing (Just $2) $5 }-| do LABEL_IN_STATEMENT ',' while '(' EXPRESSION ')'- { StDoWhile () (getTransSpan $1 $7) Nothing (Just $2) $6 }-| enddo { StEnddo () (getSpan $1) Nothing }-| call VARIABLE ARGUMENTS- { StCall () (getTransSpan $1 $3) $2 $ Just $3 }-| call VARIABLE { StCall () (getTransSpan $1 $2) $2 Nothing }-| return { StReturn () (getSpan $1) Nothing }-| return EXPRESSION { StReturn () (getTransSpan $1 $2) $ Just $2 }-| save SAVE_ARGS { StSave () (getSpan ($1, $2)) $2 }-| continue { StContinue () $ getSpan $1 }-| stop INTEGER_OR_STRING { StStop () (getTransSpan $1 $2) $ Just $2 }-| stop { StStop () (getSpan $1) Nothing }-| exit { StExit () (getSpan $1) Nothing }-| cycle { StCycle () (getSpan $1) Nothing }-| pause INTEGER_OR_STRING { StPause () (getTransSpan $1 $2) $ Just $2 }-| pause { StPause () (getSpan $1) Nothing }-| selectcase '(' EXPRESSION ')'- { StSelectCase () (getTransSpan $1 $4) Nothing $3 }-| casedefault { StCase () (getSpan $1) Nothing Nothing }-| casedefault id- { let TId s id = $2 in StCase () (getTransSpan $1 s) (Just id) Nothing }-| case '(' INDICIES ')'- { StCase () (getTransSpan $1 $4) Nothing (Just $ fromReverseList $3) }-| case '(' INDICIES ')' id- { let TId s id = $5- in StCase () (getTransSpan $1 s) (Just id) (Just $ fromReverseList $3) }-| endselect { StEndcase () (getSpan $1) Nothing }-| endselect id- { let TId s id = $2 in StEndcase () (getTransSpan $1 s) (Just id) }--- IO Statements-| read CILIST IN_IOLIST { StRead () (getTransSpan $1 $3) $2 (Just $ aReverse $3) }-| read CILIST { StRead () (getTransSpan $1 $2) $2 Nothing }-| read FORMAT_ID ',' IN_IOLIST { StRead2 () (getTransSpan $1 $4) $2 (Just $ aReverse $4) }-| read FORMAT_ID { StRead2 () (getTransSpan $1 $2) $2 Nothing }-| write CILIST OUT_IOLIST { StWrite () (getTransSpan $1 $3) $2 (Just $ aReverse $3) }-| write CILIST { StWrite () (getTransSpan $1 $2) $2 Nothing }-| print FORMAT_ID ',' OUT_IOLIST { StPrint () (getTransSpan $1 $4) $2 (Just $ aReverse $4) }-| print FORMAT_ID { StPrint () (getTransSpan $1 $2) $2 Nothing }-| typeprint FORMAT_ID ',' OUT_IOLIST { StTypePrint () (getTransSpan $1 $4) $2 (Just $ aReverse $4) }-| typeprint FORMAT_ID { StTypePrint () (getTransSpan $1 $2) $2 Nothing }-| open CILIST { StOpen () (getTransSpan $1 $2) $2 }-| close CILIST { StClose () (getTransSpan $1 $2) $2 }-| inquire CILIST { StInquire () (getTransSpan $1 $2) $2 }-| rewind CILIST { StRewind () (getTransSpan $1 $2) $2 }-| rewind UNIT { StRewind2 () (getTransSpan $1 $2) $2 }-| endfile CILIST { StEndfile () (getTransSpan $1 $2) $2 }-| endfile UNIT { StEndfile2 () (getTransSpan $1 $2) $2 }-| backspace CILIST { StBackspace () (getTransSpan $1 $2) $2 }-| backspace UNIT { StBackspace2 () (getTransSpan $1 $2) $2 }--FORMAT_ID :: { Expression A0 }-: FORMAT_ID '/' '/' FORMAT_ID %prec CONCAT { ExpBinary () (getTransSpan $1 $4) Concatenation $1 $4 }-| INTEGER_LITERAL { $1 }--- There should be FUNCTION_CALL here but as far as the parser is concerned it is same as SUBSCRIPT,--- hence putting it here would cause a reduce/reduce conflict.-| SUBSCRIPT { $1 }-| '*' { ExpValue () (getSpan $1) ValStar }--UNIT :: { Expression A0 }-: INTEGER_LITERAL { $1 }-| SUBSCRIPT { $1 }-| '*' { ExpValue () (getSpan $1) ValStar }---- A crude approximation that makes parsing easy. Individual key value pairs--- should be checket later on.-CILIST :: { AList ControlPair A0 }-: '(' UNIT ',' FORMAT_ID ',' CILIST_PAIRS ')' {- let { cp1 = ControlPair () (getSpan $2) Nothing $2;- cp2 = ControlPair () (getSpan $4) Nothing $4 }- in setSpan (getTransSpan $1 $7) $ cp1 `aCons` cp2 `aCons` aReverse $6- }-| '(' UNIT ',' FORMAT_ID ')' {- let { cp1 = ControlPair () (getSpan $2) Nothing $2;- cp2 = ControlPair () (getSpan $4) Nothing $4 }- in AList () (getTransSpan $1 $5) [ cp1, cp2 ]- }-| '(' UNIT ',' CILIST_PAIRS ')' {- let cp1 = ControlPair () (getSpan $2) Nothing $2- in setSpan (getTransSpan $1 $5) $ cp1 `aCons` aReverse $4- }-| '(' UNIT ')' {- let cp1 = ControlPair () (getSpan $2) Nothing $2- in AList () (getTransSpan $1 $3) [ cp1 ]- }-| '(' CILIST_PAIRS ')' { setSpan (getTransSpan $1 $3) $ aReverse $2 }--CILIST_PAIRS :: { AList ControlPair A0 }-: CILIST_PAIRS ',' CILIST_PAIR { setSpan (getTransSpan $1 $3) $ $3 `aCons` $1 }-| CILIST_PAIR { AList () (getSpan $1) [ $1 ] }--CILIST_PAIR :: { ControlPair A0 }-: id '=' CILIST_ELEMENT { let (TId s id) = $1 in ControlPair () (getTransSpan s $3) (Just id) $3 }--CILIST_ELEMENT :: { Expression A0 }-: CI_EXPRESSION { $1 }-| '*' { ExpValue () (getSpan $1) ValStar }--CI_EXPRESSION :: { Expression A0 }-: CI_EXPRESSION '+' CI_EXPRESSION { ExpBinary () (getTransSpan $1 $3) Addition $1 $3 }-| CI_EXPRESSION '-' CI_EXPRESSION { ExpBinary () (getTransSpan $1 $3) Subtraction $1 $3 }-| CI_EXPRESSION '*' CI_EXPRESSION { ExpBinary () (getTransSpan $1 $3) Multiplication $1 $3 }-| CI_EXPRESSION '/' CI_EXPRESSION { ExpBinary () (getTransSpan $1 $3) Division $1 $3 }-| CI_EXPRESSION '**' CI_EXPRESSION { ExpBinary () (getTransSpan $1 $3) Exponentiation $1 $3 }-| CI_EXPRESSION '/' '/' CI_EXPRESSION %prec CONCAT { ExpBinary () (getTransSpan $1 $4) Concatenation $1 $4 }-| ARITHMETIC_SIGN CI_EXPRESSION %prec NEGATION { ExpUnary () (getTransSpan (fst $1) $2) (snd $1) $2 }-| CI_EXPRESSION or CI_EXPRESSION { ExpBinary () (getTransSpan $1 $3) Or $1 $3 }-| CI_EXPRESSION and CI_EXPRESSION { ExpBinary () (getTransSpan $1 $3) And $1 $3 }-| CI_EXPRESSION xor CI_EXPRESSION { ExpBinary () (getTransSpan $1 $3) XOr $1 $3 }-| not CI_EXPRESSION { ExpUnary () (getTransSpan $1 $2) Not $2 }-| CI_EXPRESSION eqv CI_EXPRESSION { ExpBinary () (getTransSpan $1 $3) Equivalent $1 $3 }-| CI_EXPRESSION neqv CI_EXPRESSION { ExpBinary () (getTransSpan $1 $3) NotEquivalent $1 $3 }-| CI_EXPRESSION RELATIONAL_OPERATOR CI_EXPRESSION %prec RELATIONAL { ExpBinary () (getTransSpan $1 $3) $2 $1 $3 }-| '(' CI_EXPRESSION ')' { setSpan (getTransSpan $1 $3) $2 }-| INTEGER_LITERAL { $1 }-| LOGICAL_LITERAL { $1 }--- There should be FUNCTION_CALL here but as far as the parser is concerned it is same as SUBSCRIPT,--- hence putting it here would cause a reduce/reduce conflict.-| SUBSCRIPT { $1 }---- Input IOList used in read like statements is much more restrictive as it--- doesn't make sense to read into an integer.--- While the output list can be an arbitrary expression. Hence, the grammar--- rule separation.--IN_IOLIST :: { AList Expression A0 }-: IN_IOLIST ',' IN_IO_ELEMENT { setSpan (getTransSpan $1 $3) $ $3 `aCons` $1}-| IN_IO_ELEMENT { AList () (getSpan $1) [ $1 ] }--IN_IO_ELEMENT :: { Expression A0 }-: SUBSCRIPT { $1 }-| '(' IN_IOLIST ',' DO_SPECIFICATION ')' { ExpImpliedDo () (getTransSpan $1 $5) (aReverse $2) $4 }--OUT_IOLIST :: { AList Expression A0 }-: OUT_IOLIST ',' EXPRESSION { setSpan (getTransSpan $1 $3) $ $3 `aCons` $1}-| EXPRESSION { AList () (getSpan $1) [ $1 ] }--SAVE_ARGS :: { Maybe (AList Expression A0) }-: SAVE_ARGS_LEVEL1 { Just $ fromReverseList $1 }-| {-EMPTY-} { Nothing }--SAVE_ARGS_LEVEL1 :: { [ Expression A0 ] }-: SAVE_ARGS_LEVEL1 ',' SAVE_ARG { $3 : $1 }-| SAVE_ARG { [ $1 ] }--SAVE_ARG :: { Expression A0 }-: COMMON_NAME { $1 } | VARIABLE { $1 }--INTEGER_OR_STRING :: { Expression A0 } : STRING { $1 } | INTEGER_LITERAL { $1 }--GOTO_STATEMENT :: { Statement A0 }-: goto LABEL_IN_STATEMENT { StGotoUnconditional () (getTransSpan $1 $2) $2 }-| goto VARIABLE { StGotoAssigned () (getTransSpan $1 $2) $2 Nothing }-| goto VARIABLE LABELS_IN_STATEMENT { StGotoAssigned () (getTransSpan $1 $3) $2 (Just $3) }-| goto VARIABLE ',' LABELS_IN_STATEMENT { StGotoAssigned () (getTransSpan $1 $4) $2 (Just $4) }-| goto LABELS_IN_STATEMENT EXPRESSION { StGotoComputed () (getTransSpan $1 $3) $2 $3 }-| goto LABELS_IN_STATEMENT ',' EXPRESSION { StGotoComputed () (getTransSpan $1 $4) $2 $4 }--EXPRESSION_ASSIGNMENT_STATEMENT :: { Statement A0 }-: ELEMENT '=' EXPRESSION { StExpressionAssign () (getTransSpan $1 $3) $1 $3 }--NONEXECUTABLE_STATEMENT :: { Statement A0 }-: external FUNCTION_NAMES { StExternal () (getTransSpan $1 $2) (aReverse $2) }-| intrinsic FUNCTION_NAMES { StIntrinsic () (getTransSpan $1 $2) (aReverse $2) }-| dimension INITIALIZED_ARRAY_DECLARATORS { StDimension () (getTransSpan $1 $2) (aReverse $2) }-| common COMMON_GROUPS { StCommon () (getTransSpan $1 $2) (aReverse $2) }-| equivalence EQUIVALENCE_GROUPS { StEquivalence () (getTransSpan $1 $2) (aReverse $2) }-| pointer POINTER_LIST { StPointer () (getTransSpan $1 $2) (fromReverseList $2) }-| data DATA_GROUPS { StData () (getTransSpan $1 $2) (fromReverseList $2) }-| automatic INITIALIZED_DECLARATORS { StAutomatic () (getTransSpan $1 $2) (aReverse $2) }-| static INITIALIZED_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- { let TBlob s blob = $2 in StFormatBogus () (getTransSpan $1 s) blob }-| DECLARATION_STATEMENT { $1 }-| implicit none { StImplicit () (getTransSpan $1 $2) Nothing }-| implicit IMP_LISTS { StImplicit () (getTransSpan $1 $2) $ Just $ aReverse $2 }-| parameter '(' PARAMETER_ASSIGNMENTS ')'- { StParameter () (getTransSpan $1 $4) $ fromReverseList $3 }-| entry VARIABLE { StEntry () (getTransSpan $1 $2) $2 Nothing Nothing }-| entry VARIABLE ENTRY_ARGS { StEntry () (getTransSpan $1 $3) $2 (Just $3) Nothing }-| include STRING { StInclude () (getTransSpan $1 $2) $2 Nothing }-| structure MAYBE_NAME NEWLINE STRUCTURE_DECLARATIONS endstructure- { StStructure () (getTransSpan $1 $5) $2 (fromReverseList $4) }--MAYBE_NAME :: { Maybe Name }-: '/' NAME '/' { Just $2 }-| {- empty -} { Nothing }--STRUCTURE_DECLARATIONS :: { [StructureItem A0] }-: STRUCTURE_DECLARATIONS STRUCTURE_DECLARATION_STATEMENT- { if isNothing $2 then $1 else fromJust $2 : $1 }-| STRUCTURE_DECLARATION_STATEMENT { if isNothing $1 then [] else [fromJust $1] }--STRUCTURE_DECLARATION_STATEMENT :: { Maybe (StructureItem A0) }-: DECLARATION_STATEMENT NEWLINE- { let StDeclaration () s t attrs decls = $1- in Just $ StructFields () s t attrs decls }-| union NEWLINE UNION_MAPS endunion NEWLINE- { Just $ StructUnion () (getTransSpan $1 $5) (fromReverseList $3) }-| structure MAYBE_NAME NAME NEWLINE STRUCTURE_DECLARATIONS endstructure NEWLINE- { Just $ StructStructure () (getTransSpan $1 $7) $2 $3 (fromReverseList $5) }-| comment NEWLINE { Nothing }--UNION_MAPS :: { [ UnionMap A0 ] }-: UNION_MAPS UNION_MAP { if isNothing $2 then $1 else fromJust $2 : $1 }-| UNION_MAP { if isNothing $1 then [] else [fromJust $1] }--UNION_MAP :: { Maybe (UnionMap A0) }-: map NEWLINE STRUCTURE_DECLARATIONS endmap NEWLINE- { Just $ UnionMap () (getTransSpan $1 $5) (fromReverseList $3) }-| comment NEWLINE { Nothing }--ENTRY_ARGS :: { AList Expression A0 }-: ENTRY_ARGS_LEVEL1 ')' { setSpan (getTransSpan $1 $2) $ aReverse $1 }--ENTRY_ARGS_LEVEL1 :: { AList Expression A0 }-: ENTRY_ARGS_LEVEL1 ',' ENTRY_ARG { setSpan (getTransSpan $1 $3) $ $3 `aCons` $1 }-| '(' ENTRY_ARG { AList () (getTransSpan $1 $2) [ $2 ] }-| '(' { AList () (getSpan $1) [ ] }--ENTRY_ARG :: { Expression A0 }-: VARIABLE { $1 }-| '*' { ExpValue () (getSpan $1) ValStar }--PARAMETER_ASSIGNMENTS :: { [ Declarator A0 ] }-: PARAMETER_ASSIGNMENTS ',' PARAMETER_ASSIGNMENT { $3 : $1 }-| PARAMETER_ASSIGNMENT { [ $1 ] }--PARAMETER_ASSIGNMENT :: { Declarator A0 }-: VARIABLE '=' CONSTANT_EXPRESSION- { Declarator () (getTransSpan $1 $3) $1 ScalarDecl Nothing (Just $3) }--DECLARATION_STATEMENT :: { Statement A0 }-: TYPE_SPEC maybe(',') INITIALIZED_DECLARATORS- { StDeclaration () (getTransSpan $1 $3) $1 Nothing (aReverse $3) }--IMP_LISTS :: { AList ImpList A0 }-: IMP_LISTS ',' IMP_LIST { setSpan (getTransSpan $1 $3) $ $3 `aCons` $1 }-| IMP_LIST { AList () (getSpan $1) [ $1 ] }--IMP_LIST :: { ImpList A0 }-: IMP_TYPE_SPEC '(' IMP_ELEMENTS ')'- { ImpList () (getTransSpan $1 $4) $1 $ aReverse $3 }--IMP_ELEMENTS :: { AList ImpElement A0 }-: IMP_ELEMENTS ',' IMP_ELEMENT { setSpan (getTransSpan $1 $3) $ $3 `aCons` $1 }-| IMP_ELEMENT { AList () (getSpan $1) [ $1 ] }--IMP_ELEMENT :: { ImpElement A0 }-: id {% do- let (TId s id) = $1- if length id /= 1- then fail "Implicit argument must be a character."- else return $ ImpCharacter () s id- }-| id '-' id {% do- let (TId _ id1) = $1- let (TId _ id2) = $3- if length id1 /= 1 || length id2 /= 1- then fail "Implicit argument must be a character."- else return $ ImpRange () (getTransSpan $1 $3) id1 id2- }--ELEMENT :: { Expression A0 }-: SUBSCRIPT { $1 }--DATA_GROUPS :: { [DataGroup A0] }-: DATA_GROUPS ',' DATA_GROUP { $3 : $1 }-| DATA_GROUPS DATA_GROUP { $2 : $1 }-| DATA_GROUP { [$1] }--DATA_GROUP :: { DataGroup A0 }-: DATA_NAMES '/' DATA_ITEMS '/' { DataGroup () (getTransSpan $1 $4) (aReverse $1) (aReverse $3) }--DATA_NAMES :: { AList Expression A0 }-: NAME_LIST { $1 }-| IMPLIED_DO { fromList () [ $1 ] }--DATA_ITEMS :: { AList Expression A0 }-: DATA_ITEMS ',' DATA_ITEM { setSpan (getTransSpan $1 $3) $ $3 `aCons` $1}-| DATA_ITEM { AList () (getSpan $1) [ $1 ] }--DATA_ITEM :: { Expression A0 }-: INTEGER_CONSTANT '*' DATA_ITEM_LEVEL1 { ExpBinary () (getTransSpan $1 $3) Multiplication $1 $3 }-| DATA_ITEM_LEVEL1 { $1 }--DATA_ITEM_LEVEL1 :: { Expression A0 }-: SIGNED_NUMERIC_LITERAL { $1 }--- | COMPLEX_LITERAL { $1 }-| VARIABLE { $1 }-| '(' SIGNED_NUMERIC_LITERAL ',' SIGNED_NUMERIC_LITERAL ')' { ExpValue () (getTransSpan $1 $5) (ValComplex $2 $4)}-| LOGICAL_LITERAL { $1 }-| STRING { $1 }-| HOLLERITH { $1 }--EQUIVALENCE_GROUPS :: { AList (AList Expression) A0 }-: EQUIVALENCE_GROUPS ',' '(' NAME_LIST ')' { setSpan (getTransSpan $1 $5) $ (setSpan (getTransSpan $3 $5) $ aReverse $4) `aCons` $1 }-| '(' NAME_LIST ')' { let s = (getTransSpan $1 $3) in AList () s [ setSpan s $ aReverse $2 ] }--POINTER_LIST :: { [ Declarator A0 ] }-: POINTER_LIST ',' POINTER { $3 : $1 }-| POINTER { [ $1 ] }--POINTER :: { Declarator A0 }-: '(' VARIABLE ',' VARIABLE ')'- { Declarator () (getTransSpan $1 $5) $2 ScalarDecl Nothing (Just $4) }--COMMON_GROUPS :: { AList CommonGroup A0 }-: COMMON_GROUPS COMMON_GROUP { setSpan (getTransSpan $1 $2) $ $2 `aCons` $1 }-| INIT_COMMON_GROUP { AList () (getSpan $1) [ $1 ] }--COMMON_GROUP :: { CommonGroup A0 }-: COMMON_NAME UNINITIALIZED_DECLARATORS { CommonGroup () (getTransSpan $1 $2) (Just $1) $ aReverse $2 }-| '/' '/' UNINITIALIZED_DECLARATORS { CommonGroup () (getTransSpan $1 $3) Nothing $ aReverse $3 }--INIT_COMMON_GROUP :: { CommonGroup A0 }-: COMMON_NAME UNINITIALIZED_DECLARATORS { CommonGroup () (getTransSpan $1 $2) (Just $1) $ aReverse $2 }-| '/' '/' UNINITIALIZED_DECLARATORS { CommonGroup () (getTransSpan $1 $3) Nothing $ aReverse $3 }-| UNINITIALIZED_DECLARATORS { CommonGroup () (getSpan $1) Nothing $ aReverse $1 }--COMMON_NAME :: { Expression A0 }-: '/' VARIABLE '/' { setSpan (getTransSpan $1 $3) $2 }--NAME_LIST :: { AList Expression A0 }-: NAME_LIST ',' ELEMENT- { setSpan (getTransSpan $1 $3) $ $3 `aCons` $1 }-| ELEMENT { AList () (getSpan $1) [ $1 ] }--UNINITIALIZED_DECLARATORS :: { AList Declarator A0 }-: UNINITIALIZED_DECLARATORS ',' UNINITIALIZED_DECLARATOR { setSpan (getTransSpan $1 $3) $ $3 `aCons` $1 }-| UNINITIALIZED_DECLARATOR { AList () (getSpan $1) [ $1 ] }--UNINITIALIZED_DECLARATOR :: { Declarator A0 }-: UNINITIALIZED_ARRAY_DECLARATOR { $1 }-| UNINITIALIZED_VARIABLE_DECLARATOR { $1 }--UNINITIALIZED_ARRAY_DECLARATOR :: { Declarator A0 }-: VARIABLE '(' DIMENSION_DECLARATORS ')'- { Declarator () (getTransSpan $1 $4) $1 (ArrayDecl (aReverse $3)) Nothing Nothing }-| VARIABLE '*' SIMPLE_EXPRESSION '(' DIMENSION_DECLARATORS ')'- { Declarator () (getTransSpan $1 $6) $1 (ArrayDecl (aReverse $5)) (Just $3) Nothing }-| VARIABLE '(' DIMENSION_DECLARATORS ')' '*' SIMPLE_EXPRESSION- { Declarator () (getTransSpan $1 $6) $1 (ArrayDecl (aReverse $3)) (Just $6) Nothing }--UNINITIALIZED_VARIABLE_DECLARATOR :: { Declarator A0 }-: VARIABLE- { Declarator () (getSpan $1) $1 ScalarDecl Nothing Nothing }-| VARIABLE '*' SIMPLE_EXPRESSION- { Declarator () (getTransSpan $1 $3) $1 ScalarDecl (Just $3) Nothing }--INITIALIZED_DECLARATORS :: { AList Declarator A0 }-: INITIALIZED_DECLARATORS ',' INITIALIZED_DECLARATOR { setSpan (getTransSpan $1 $3) $ $3 `aCons` $1 }-| INITIALIZED_DECLARATOR { AList () (getSpan $1) [ $1 ] }--INITIALIZED_DECLARATOR :: { Declarator A0 }-: INITIALIZED_ARRAY_DECLARATOR { $1 }-| INITIALIZED_VARIABLE_DECLARATOR { $1 }--INITIALIZED_ARRAY_DECLARATORS :: { AList Declarator A0 }-: INITIALIZED_ARRAY_DECLARATORS ',' INITIALIZED_ARRAY_DECLARATOR- { setSpan (getTransSpan $1 $3) $ $3 `aCons` $1 }-| INITIALIZED_ARRAY_DECLARATOR { AList () (getSpan $1) [ $1 ] }--INITIALIZED_ARRAY_DECLARATOR :: { Declarator A0 }-: UNINITIALIZED_ARRAY_DECLARATOR { $1 }-| VARIABLE '(' DIMENSION_DECLARATORS ')' '/' SIMPLE_EXPRESSION_LIST '/'- { Declarator () (getTransSpan $1 $7) $1 (ArrayDecl (aReverse $3)) Nothing- (Just (ExpInitialisation () (getSpan $6) (fromReverseList $6))) }-| VARIABLE '*' SIMPLE_EXPRESSION '(' DIMENSION_DECLARATORS ')' '/' SIMPLE_EXPRESSION_LIST '/'- { Declarator () (getTransSpan $1 $9) $1 (ArrayDecl (aReverse $5)) (Just $3)- (Just (ExpInitialisation () (getSpan $8) (fromReverseList $8))) }-| VARIABLE '(' DIMENSION_DECLARATORS ')' '*' SIMPLE_EXPRESSION '/' SIMPLE_EXPRESSION_LIST '/'- { Declarator () (getTransSpan $1 $9) $1 (ArrayDecl (aReverse $3)) (Just $6)- (Just (ExpInitialisation () (getSpan $8) (fromReverseList $8))) }--INITIALIZED_VARIABLE_DECLARATOR :: { Declarator A0 }-: UNINITIALIZED_VARIABLE_DECLARATOR { $1 }-| VARIABLE '/' SIMPLE_EXPRESSION '/'- { Declarator () (getTransSpan $1 $4) $1 ScalarDecl Nothing (Just $3) }-| VARIABLE '*' SIMPLE_EXPRESSION '/' SIMPLE_EXPRESSION '/'- { Declarator () (getTransSpan $1 $6) $1 ScalarDecl (Just $3) (Just $5) }--SIMPLE_EXPRESSION_LIST :: { [Expression A0] }-: SIMPLE_EXPRESSION_LIST ',' SIMPLE_EXPRESSION { $3 : $1 }-| SIMPLE_EXPRESSION { [ $1 ] }--SIMPLE_EXPRESSION :: { Expression A0 }-: INTEGER_CONSTANT '*' CONSTANT { ExpBinary () (getTransSpan $1 $3) Multiplication $1 $3 }-| CONSTANT { $1 }-| '(' '*' ')' { ExpValue () (getSpan $2) ValStar }-| '(' EXPRESSION ')' { $2 }--CONSTANT :: { Expression A0 }-: VARIABLE { $1 }-| SIGNED_NUMERIC_LITERAL { $1 }-| LOGICAL_LITERAL { $1 }-| STRING { $1 }-| HOLLERITH { $1 }--INTEGER_CONSTANT :: { Expression A0 }-: VARIABLE { $1 }-| SIGNED_NUMERIC_LITERAL { $1 }--DIMENSION_DECLARATORS :: { AList DimensionDeclarator A0 }-: DIMENSION_DECLARATORS ',' DIMENSION_DECLARATOR- { setSpan (getTransSpan $1 $3) $ $3 `aCons` $1 }-| DIMENSION_DECLARATOR { AList () (getSpan $1) [ $1 ] }--DIMENSION_DECLARATOR :: { DimensionDeclarator A0 }-: EXPRESSION ':' EXPRESSION { DimensionDeclarator () (getTransSpan $1 $3) (Just $1) (Just $3) }-| EXPRESSION { DimensionDeclarator () (getSpan $1) Nothing (Just $1) }-| EXPRESSION ':' '*' { DimensionDeclarator () (getTransSpan $1 $3) (Just $1) (Just $ ExpValue () (getSpan $3) ValStar) }-| '*' { DimensionDeclarator () (getSpan $1) Nothing (Just $ ExpValue () (getSpan $1) ValStar) }---- Here the procedure should be either a function or subroutine name, but--- since they are syntactically identical at this stage subroutine names--- are also emitted as function names.-FUNCTION_NAMES :: { AList Expression A0 }-: FUNCTION_NAMES ',' VARIABLE { setSpan (getTransSpan $1 $3) $ $3 `aCons` $1 }-| VARIABLE { AList () (getSpan $1) [ $1 ] }--ARGUMENTS :: { AList Argument A0 }-: ARGUMENTS_LEVEL1 ')' { setSpan (getTransSpan $1 $2) $ aReverse $1 }--ARGUMENTS_LEVEL1 :: { AList Argument A0 }-: ARGUMENTS_LEVEL1 ',' CALLABLE_EXPRESSION { setSpan (getTransSpan $1 $3) $ $3 `aCons` $1 }-| '(' CALLABLE_EXPRESSION { AList () (getTransSpan $1 $2) [ $2 ] }-| '(' { AList () (getSpan $1) [ ] }---- Expression all by itself subsumes all other callable expressions.-CALLABLE_EXPRESSION :: { Argument A0 }--- 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 }--EXPRESSION :: { Expression A0 }-: EXPRESSION '+' EXPRESSION { ExpBinary () (getTransSpan $1 $3) Addition $1 $3 }-| EXPRESSION '-' EXPRESSION { ExpBinary () (getTransSpan $1 $3) Subtraction $1 $3 }-| EXPRESSION '*' EXPRESSION { ExpBinary () (getTransSpan $1 $3) Multiplication $1 $3 }-| EXPRESSION '/' EXPRESSION { ExpBinary () (getTransSpan $1 $3) Division $1 $3 }-| EXPRESSION '**' EXPRESSION { ExpBinary () (getTransSpan $1 $3) Exponentiation $1 $3 }-| EXPRESSION '/' '/' EXPRESSION %prec CONCAT { ExpBinary () (getTransSpan $1 $4) Concatenation $1 $4 }-| ARITHMETIC_SIGN EXPRESSION %prec NEGATION { ExpUnary () (getTransSpan (fst $1) $2) (snd $1) $2 }-| EXPRESSION or EXPRESSION { ExpBinary () (getTransSpan $1 $3) Or $1 $3 }-| EXPRESSION xor EXPRESSION { ExpBinary () (getTransSpan $1 $3) XOr $1 $3 }-| EXPRESSION and EXPRESSION { ExpBinary () (getTransSpan $1 $3) And $1 $3 }-| not EXPRESSION { ExpUnary () (getTransSpan $1 $2) Not $2 }-| EXPRESSION eqv EXPRESSION { ExpBinary () (getTransSpan $1 $3) Equivalent $1 $3 }-| EXPRESSION neqv EXPRESSION { ExpBinary () (getTransSpan $1 $3) NotEquivalent $1 $3 }-| EXPRESSION RELATIONAL_OPERATOR EXPRESSION %prec RELATIONAL { ExpBinary () (getTransSpan $1 $3) $2 $1 $3 }-| '(' EXPRESSION ')' { setSpan (getTransSpan $1 $3) $2 }-| NUMERIC_LITERAL { $1 }-| '(' EXPRESSION ',' EXPRESSION ')' { ExpValue () (getTransSpan $1 $5) (ValComplex $2 $4) }-| LOGICAL_LITERAL { $1 }-| HOLLERITH { $1 }--- There should be FUNCTION_CALL here but as far as the parser is concerned it is same as SUBSCRIPT,--- hence putting it here would cause a reduce/reduce conflict.-| SUBSCRIPT { $1 }-| IMPLIED_DO { $1 }-| '(/' EXPRESSION_LIST '/)' {- let { exps = reverse $2;- expList = AList () (getSpan exps) exps }- in ExpInitialisation () (getTransSpan $1 $3) expList- }-| '*' INTEGER_LITERAL { ExpReturnSpec () (getTransSpan $1 $2) $2 }-| '&' INTEGER_LITERAL { ExpReturnSpec () (getTransSpan $1 $2) $2 }--IMPLIED_DO :: { Expression A0 }-: '(' EXPRESSION ',' DO_SPECIFICATION ')' {- let expList = AList () (getSpan $2) [ $2 ]- in ExpImpliedDo () (getTransSpan $1 $5) expList $4- }-| '(' EXPRESSION ',' EXPRESSION ',' DO_SPECIFICATION ')' {- let expList = AList () (getTransSpan $2 $4) [ $2, $4 ]- in ExpImpliedDo () (getTransSpan $1 $5) expList $6- }-| '(' EXPRESSION ',' EXPRESSION ',' EXPRESSION_LIST ',' DO_SPECIFICATION ')' {- let { exps = reverse $6;- expList = AList () (getTransSpan $2 exps) ($2 : $4 : reverse $6) }- in ExpImpliedDo () (getTransSpan $1 $9) expList $8- }--EXPRESSION_LIST :: { [ Expression A0 ] }-: EXPRESSION_LIST ',' EXPRESSION { $3 : $1 }-| EXPRESSION { [ $1 ] }--STRING :: { Expression A0 } : string { let (TString s cs) = $1 in ExpValue () s (ValString cs) }--CONSTANT_EXPRESSION :: { Expression A0 }-: CONSTANT_EXPRESSION '+' CONSTANT_EXPRESSION { ExpBinary () (getTransSpan $1 $3) Addition $1 $3 }-| CONSTANT_EXPRESSION '-' CONSTANT_EXPRESSION { ExpBinary () (getTransSpan $1 $3) Subtraction $1 $3 }-| CONSTANT_EXPRESSION '*' CONSTANT_EXPRESSION { ExpBinary () (getTransSpan $1 $3) Multiplication $1 $3 }-| CONSTANT_EXPRESSION '/' CONSTANT_EXPRESSION { ExpBinary () (getTransSpan $1 $3) Division $1 $3 }-| CONSTANT_EXPRESSION '**' CONSTANT_EXPRESSION { ExpBinary () (getTransSpan $1 $3) Exponentiation $1 $3 }-| CONSTANT_EXPRESSION '/' '/' CONSTANT_EXPRESSION %prec CONCAT { ExpBinary () (getTransSpan $1 $4) Concatenation $1 $4 }-| ARITHMETIC_SIGN CONSTANT_EXPRESSION %prec NEGATION { ExpUnary () (getTransSpan (fst $1) $2) (snd $1) $2 }-| CONSTANT_EXPRESSION or CONSTANT_EXPRESSION { ExpBinary () (getTransSpan $1 $3) Or $1 $3 }-| CONSTANT_EXPRESSION xor CONSTANT_EXPRESSION { ExpBinary () (getTransSpan $1 $3) XOr $1 $3 }-| CONSTANT_EXPRESSION and CONSTANT_EXPRESSION { ExpBinary () (getTransSpan $1 $3) And $1 $3 }-| not CONSTANT_EXPRESSION { ExpUnary () (getTransSpan $1 $2) Not $2 }-| CONSTANT_EXPRESSION RELATIONAL_OPERATOR CONSTANT_EXPRESSION %prec RELATIONAL { ExpBinary () (getTransSpan $1 $3) $2 $1 $3 }-| '(' CONSTANT_EXPRESSION ')' { setSpan (getTransSpan $1 $3) $2 }-| NUMERIC_LITERAL { $1 }-| '(' CONSTANT_EXPRESSION ',' CONSTANT_EXPRESSION ')' { ExpValue () (getTransSpan $1 $5) (ValComplex $2 $4)}-| LOGICAL_LITERAL { $1 }-| SUBSCRIPT { $1 }-| HOLLERITH { $1 }-| '(/' EXPRESSION_LIST '/)' {- let { exps = reverse $2;- expList = AList () (getSpan exps) exps }- in ExpInitialisation () (getTransSpan $1 $3) expList- }--ARITHMETIC_CONSTANT_EXPRESSION :: { Expression A0 }-: ARITHMETIC_CONSTANT_EXPRESSION '+' ARITHMETIC_CONSTANT_EXPRESSION { ExpBinary () (getTransSpan $1 $3) Addition $1 $3 }-| ARITHMETIC_CONSTANT_EXPRESSION '-' ARITHMETIC_CONSTANT_EXPRESSION { ExpBinary () (getTransSpan $1 $3) Subtraction $1 $3 }-| ARITHMETIC_CONSTANT_EXPRESSION '*' ARITHMETIC_CONSTANT_EXPRESSION { ExpBinary () (getTransSpan $1 $3) Multiplication $1 $3 }-| ARITHMETIC_CONSTANT_EXPRESSION '/' ARITHMETIC_CONSTANT_EXPRESSION { ExpBinary () (getTransSpan $1 $3) Division $1 $3 }-| ARITHMETIC_CONSTANT_EXPRESSION '**' ARITHMETIC_CONSTANT_EXPRESSION { ExpBinary () (getTransSpan $1 $3) Exponentiation $1 $3 }-| ARITHMETIC_SIGN ARITHMETIC_CONSTANT_EXPRESSION %prec NEGATION { ExpUnary () (getTransSpan (fst $1) $2) (snd $1) $2 }-| '(' ARITHMETIC_CONSTANT_EXPRESSION ')' { setSpan (getTransSpan $1 $3) $2 }-| NUMERIC_LITERAL { $1 }-| '(' ARITHMETIC_CONSTANT_EXPRESSION ',' ARITHMETIC_CONSTANT_EXPRESSION ')' { ExpValue () (getTransSpan $1 $5) (ValComplex $2 $4)}-| VARIABLE { $1 }-| SUBSCRIPT { $1 }--RELATIONAL_OPERATOR :: { BinaryOp }-: '==' { EQ }-| '!=' { NE }-| '>' { GT }-| '>=' { GTE }-| '<' { LT }-| '<=' { LTE }--SUBSCRIPT :: { Expression A0 }-: 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 ')'- { ExpSubscript () (getTransSpan $1 $4) $1 (fromReverseList $3) }-| VARIABLE { $1 }-| STRING { $1 }--INDICIES :: { [ Index A0 ] }-: INDICIES ',' INDEX { $3 : $1 }-| INDEX { [ $1 ] }--INDEX :: { Index A0 }-: RANGE { $1 }-| EXPRESSION { IxSingle () (getSpan $1) Nothing $1 }--RANGE :: { Index A0 }-: ':' { IxRange () (getSpan $1) Nothing Nothing Nothing }-| ':' EXPRESSION { IxRange () (getTransSpan $1 $2) Nothing (Just $2) Nothing }-| EXPRESSION ':' { IxRange () (getTransSpan $1 $2) (Just $1) Nothing Nothing }-| EXPRESSION ':' EXPRESSION- { IxRange () (getTransSpan $1 $3) (Just $1) (Just $3) Nothing }--ARITHMETIC_SIGN :: { (SrcSpan, UnaryOp) }-: '-' { (getSpan $1, Minus) }-| '+' { (getSpan $1, Plus) }--MAYBE_VARIABLES :: { Maybe (AList Expression A0) }-: VARIABLES { Just $ fromReverseList $1 } | {- EMPTY -} { Nothing }--VARIABLES :: { [ Expression A0 ] }-: VARIABLES ',' VARIABLE_OR_STAR { $3 : $1 }-| VARIABLE_OR_STAR { [ $1 ] }--VARIABLE_OR_STAR :: { Expression A0 }-: VARIABLE { $1 }-| '*' { ExpValue () (getSpan $1) ValStar }-| '&' { ExpValue () (getSpan $1) ValStar }---- This may also be used to parse a function name, or an array name. Since when--- are valid options in a production there is no way of differentiating them at--- this stage.--- This at least reduces reduce/reduce conflicts.-VARIABLE :: { Expression A0 }-: id { ExpValue () (getSpan $1) $ let (TId _ s) = $1 in ValVariable s }--INTEGER_LITERAL :: { Expression A0 }-: int { ExpValue () (getSpan $1) $ let (TInt _ i) = $1 in ValInteger i Nothing}-| boz { let TBozLiteral s b = $1 in ExpValue () s $ ValBoz b }--REAL_LITERAL :: { Expression A0 }-: int EXPONENT { makeReal (Just $1) Nothing Nothing (Just $2) }-| int '.' MAYBE_EXPONENT { makeReal (Just $1) (Just $2) Nothing $3 }-| '.' int MAYBE_EXPONENT { makeReal Nothing (Just $1) (Just $2) $3 }-| int '.' int MAYBE_EXPONENT { makeReal (Just $1) (Just $2) (Just $3) $4 }--MAYBE_EXPONENT :: { Maybe (SrcSpan, String) }-: EXPONENT { Just $1 }-| {-EMPTY-} { Nothing }--EXPONENT :: { (SrcSpan, String) }-: exponent { let (TExponent s exp) = $1 in (s, exp) }--SIGNED_NUMERIC_LITERAL :: { Expression A0 }-: ARITHMETIC_SIGN NUMERIC_LITERAL { ExpUnary () (getTransSpan (fst $1) $2) Minus $2 }-| NUMERIC_LITERAL { $1 }--NUMERIC_LITERAL :: { Expression A0 }-: INTEGER_LITERAL { $1 }-| REAL_LITERAL { $1 }--LOGICAL_LITERAL :: { Expression A0 }-: bool { let TBool s b = $1 in ExpValue () s $ ValLogical b Nothing }--HOLLERITH :: { Expression A0 } : hollerith { ExpValue () (getSpan $1) $ let (THollerith _ h) = $1 in ValHollerith h }--LABELS_IN_STATEMENT :: { AList Expression A0 }-: LABELS_IN_STATEMENT_LEVEL1 ')' { setSpan (getTransSpan $1 $2) $ aReverse $1 }--LABELS_IN_STATEMENT_LEVEL1 :: { AList Expression A0 }-: LABELS_IN_STATEMENT_LEVEL1 ',' LABEL_IN_STATEMENT { setSpan (getTransSpan $1 $3) $ $3 `aCons` $1 }-| '(' LABEL_IN_STATEMENT { AList () (getTransSpan $1 $2) [ $2 ] }---- Labels that occur in the first 6 columns-LABEL_IN_6COLUMN :: { Expression A0 } : label { ExpValue () (getSpan $1) (let (TLabel _ l) = $1 in ValInteger l Nothing) }---- Labels that occur in statements-LABEL_IN_STATEMENT :: { Expression A0 } : int { ExpValue () (getSpan $1) (let (TInt _ l) = $1 in ValInteger l Nothing) }--TYPE_SPEC :: { TypeSpec A0 }-: integer KIND_SELECTOR { TypeSpec () (getSpan ($1, $2)) TypeInteger $2 }-| real KIND_SELECTOR { TypeSpec () (getSpan ($1, $2)) TypeReal $2 }-| doublePrecision { TypeSpec () (getSpan $1) TypeDoublePrecision Nothing}-| logical KIND_SELECTOR { TypeSpec () (getSpan ($1, $2)) TypeLogical $2 }-| complex KIND_SELECTOR { TypeSpec () (getSpan ($1, $2)) TypeComplex $2 }-| doubleComplex { TypeSpec () (getSpan $1) TypeDoubleComplex Nothing}-| character CHAR_SELECTOR { TypeSpec () (getSpan ($1, $2)) TypeCharacter $2 }-| byte KIND_SELECTOR { TypeSpec () (getSpan ($1, $2)) TypeByte $2 }-| record '/' NAME '/' { TypeSpec () (getSpan ($1, $4)) (TypeCustom $3) Nothing }--KIND_SELECTOR :: { Maybe (Selector A0) }-: KIND_SELECTOR1 { Just $1 }-| {- EMPTY -} { Nothing }--KIND_SELECTOR1 :: { Selector A0 }-: '*' ARITHMETIC_CONSTANT_EXPRESSION- { Selector () (getTransSpan $1 $2) Nothing (Just $2) }-| '*' '(' STAR ')' { Selector () (getTransSpan $1 $4) Nothing (Just $3) }--CHAR_SELECTOR :: { Maybe (Selector A0) }-: CHAR_SELECTOR1 { Just $1 }-| {- EMPTY -} { Nothing }--CHAR_SELECTOR1 :: { Selector A0 }-: '*' ARITHMETIC_CONSTANT_EXPRESSION- { Selector () (getTransSpan $1 $2) (Just $2) Nothing }-| '*' '(' STAR ')'- { Selector () (getTransSpan $1 $4) (Just $3) Nothing }--IMP_TYPE_SPEC :: { TypeSpec A0 }-: TYPE_SPEC { $1 }--STAR :: { Expression A0 }-STAR : '*' { ExpValue () (getSpan $1) ValStar }--{--parse = runParse programParser--defTransforms77 = defaultTransformations Fortran77-defTransforms77e = defaultTransformations Fortran77Extended-defTransforms77l = defaultTransformations Fortran77Legacy--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 transforms- parseState = initParseState sourceCode Fortran77Extended filename--extended77Parser- :: B.ByteString -> String -> ParseResult AlexInput Token (ProgramFile A0)-extended77Parser = extended77ParserWithTransforms defTransforms77e--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 transforms- parseState = initParseState sourceCode Fortran77Extended filename--legacy77Parser- :: B.ByteString -> String -> ParseResult AlexInput Token (ProgramFile A0)-legacy77Parser = legacy77ParserWithTransforms defTransforms77l--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 transforms- parseState = initParseState sourceCode Fortran77Legacy 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' <- evalStateT (descendBiM (inlineInclude Fortran77Legacy incs []) p) M.empty- return (ParseOk p' x)- transform = transformWithModFiles emptyModFiles transforms- parseState = initParseState sourceCode Fortran77Legacy filename--includeParser ::- FortranVersion -> B.ByteString -> String -> ParseResult AlexInput Token [Block A0]-includeParser version sourceCode filename =- runParse includesParser parseState- where- -- ensure the file ends with a newline..- parseState = initParseState (sourceCode `B.snoc` '\n') version filename--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- incMap <- get- case M.lookup path incMap of- Just blocks' -> pure $ StInclude a s e (Just blocks')- Nothing -> do- (fullPath, inc) <- liftIO $ readInDirs dirs path- case includeParser fv inc fullPath 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--readInDirs :: [String] -> String -> IO (String, B.ByteString)-readInDirs [] f = fail $ "cannot find file: " ++ f-readInDirs (d:ds) f = do- let path = d</>f- b <- doesFileExist path- if b then- (path,) <$> B.readFile path- else- readInDirs ds f--parseError :: Token -> LexAction a-parseError _ = do- parseState <- get-#ifdef DEBUG- tokens <- reverse <$> aiPreviousTokensInLine <$> getAlex-#endif- fail $ psFilename parseState ++ ": parsing failed. "-#ifdef DEBUG- ++ '\n' : show tokens-#endif---}
− src/Language/Fortran/Parser/Fortran90.y
@@ -1,1214 +0,0 @@--- -*- Mode: Haskell -*--{-module Language.Fortran.Parser.Fortran90 ( statementParser- , functionParser- , blockParser- , fortran90Parser- , fortran90ParserWithTransforms- , fortran90ParserWithModFiles- , fortran90ParserWithModFilesWithTransforms- ) where--import Prelude hiding (EQ,LT,GT) -- Same constructors exist in the AST-import Control.Monad.State (get)-import Data.Maybe (fromMaybe)-import Data.Either (partitionEithers)-import qualified Data.ByteString.Char8 as B--import Control.Monad.State-#ifdef DEBUG-import Data.Data (toConstr)-#endif--import Language.Fortran.Util.Position-import Language.Fortran.Util.ModFile-import Language.Fortran.ParserMonad-import Language.Fortran.Lexer.FreeForm-import Language.Fortran.AST-import Language.Fortran.Transformer--import Debug.Trace--}--%name programParser PROGRAM-%name functionParser SUBPROGRAM_UNIT-%name statementParser STATEMENT-%name blockParser BLOCK-%monad { LexAction }-%lexer { lexer } { TEOF _ }-%tokentype { Token }-%error { parseError }--%token- id { TId _ _ }- comment { TComment _ _ }- string { TString _ _ }- int { TIntegerLiteral _ _ }- float { TRealLiteral _ _ }- boz { TBozLiteral _ _ }- '_' { TUnderscore _ }- ',' { TComma _ }- ',2' { TComma2 _ }- ';' { TSemiColon _ }- ':' { TColon _ }- '::' { TDoubleColon _ }- '=' { TOpAssign _ }- '=>' { TArrow _ }- '%' { TPercent _ }- '(' { TLeftPar _ }- '(2' { TLeftPar2 _ }- ')' { TRightPar _ }- '(/' { TLeftInitPar _ }- '/)' { TRightInitPar _ }- opCustom { TOpCustom _ _ }- '**' { TOpExp _ }- '+' { TOpPlus _ }- '-' { TOpMinus _ }- '*' { TStar _ }- '/' { TOpDivision _ }- slash { TSlash _ }- or { TOpOr _ }- and { TOpAnd _ }- not { TOpNot _ }- eqv { TOpEquivalent _ }- neqv { TOpNotEquivalent _ }- '<' { TOpLT _ }- '<=' { TOpLE _ }- '==' { TOpEQ _ }- '!=' { TOpNE _ }- '>' { TOpGT _ }- '>=' { TOpGE _ }- bool { TLogicalLiteral _ _ }- program { TProgram _ }- endProgram { TEndProgram _ }- function { TFunction _ }- endFunction { TEndFunction _ }- result { TResult _ }- recursive { TRecursive _ }- subroutine { TSubroutine _ }- endSubroutine { TEndSubroutine _ }- blockData { TBlockData _ }- endBlockData { TEndBlockData _ }- module { TModule _ }- endModule { TEndModule _ }- contains { TContains _ }- use { TUse _ }- only { TOnly _ }- interface { TInterface _ }- endInterface { TEndInterface _ }- moduleProcedure { TModuleProcedure _ }- assignment { TAssignment _ }- operator { TOperator _ }- call { TCall _ }- return { TReturn _ }- entry { TEntry _ }- include { TInclude _ }- public { TPublic _ }- private { TPrivate _ }- parameter { TParameter _ }- allocatable { TAllocatable _ }- dimension { TDimension _ }- external { TExternal _ }- intent { TIntent _ }- intrinsic { TIntrinsic _ }- optional { TOptional _ }- pointer { TPointer _ }- save { TSave _ }- target { TTarget _ }- in { TIn _ }- out { TOut _ }- inout { TInOut _ }- data { TData _ }- namelist { TNamelist _ }- implicit { TImplicit _ }- equivalence { TEquivalence _ }- common { TCommon _ }- allocate { TAllocate _ }- stat { TStat _ }- deallocate { TDeallocate _ }- nullify { TNullify _ }- none { TNone _ }- goto { TGoto _ }- assign { TAssign _ }- to { TTo _ }- continue { TContinue _ }- stop { TStop _ }- pause { TPause _ }- do { TDo _ }- enddo { TEndDo _ }- while { TWhile _ }- if { TIf _ }- then { TThen _ }- else { TElse _ }- elsif { TElsif _ }- endif { TEndIf _ }- case { TCase _ }- selectcase { TSelectCase _ }- endselect { TEndSelect _ }- default { TDefault _ }- cycle { TCycle _ }- exit { TExit _ }- where { TWhere _ }- elsewhere { TElsewhere _ }- endwhere { TEndWhere _ }- type { TType _ }- endType { TEndType _ }- sequence { TSequence _ }- kind { TKind _ }- len { TLen _ }- integer { TInteger _ }- real { TReal _ }- doublePrecision { TDoublePrecision _ }- logical { TLogical _ }- character { TCharacter _ }- complex { TComplex _ }- open { TOpen _ }- close { TClose _ }- read { TRead _ }- write { TWrite _ }- print { TPrint _ }- backspace { TBackspace _ }- rewind { TRewind _ }- inquire { TInquire _ }- endfile { TEndfile _ }- format { TFormat _ }- blob { TBlob _ _ }- end { TEnd _ }- newline { TNewline _ }---- Precedence of operators---- Level 6-%left opCustom---- Level 5-%left eqv neqv-%left or-%left and-%right not---- Level 4-%nonassoc '==' '!=' '>' '<' '>=' '<='-%nonassoc RELATIONAL---- Level 3-%left CONCAT---- Level 2-%left '+' '-'-%left '*' '/'-%right SIGN-%right '**'---- Level 1-%right DEFINED_UNARY---- Level 0-%left '%'--%%--maybe(p)-: p { Just $1 }-| {- empty -} { Nothing }---- This rule is to ignore leading whitespace-PROGRAM :: { ProgramFile A0 }-: NEWLINE PROGRAM_INNER { $2 }-| PROGRAM_INNER { $1 }--PROGRAM_INNER :: { ProgramFile A0 }-: PROGRAM_UNITS { ProgramFile (MetaInfo { miVersion = Fortran90, miFilename = "" }) (reverse $1) }-| {- empty -} { ProgramFile (MetaInfo { miVersion = Fortran90, miFilename = "" }) [] }--PROGRAM_UNITS :: { [ ProgramUnit A0 ] }-: PROGRAM_UNITS PROGRAM_UNIT MAYBE_NEWLINE { $2 : $1 }-| PROGRAM_UNIT MAYBE_NEWLINE { [ $1 ] }--PROGRAM_UNIT :: { ProgramUnit A0 }-: program NAME NEWLINE BLOCKS MAYBE_SUBPROGRAM_UNITS PROGRAM_END- {% do { unitNameCheck $6 $2;- return $ PUMain () (getTransSpan $1 $6) (Just $2) (reverse $4) $5 } }-| module NAME NEWLINE BLOCKS MAYBE_SUBPROGRAM_UNITS MODULE_END- {% do { unitNameCheck $6 $2;- return $ PUModule () (getTransSpan $1 $6) $2 (reverse $4) $5 } }-| blockData NEWLINE BLOCKS BLOCK_DATA_END- { PUBlockData () (getTransSpan $1 $4) Nothing (reverse $3) }-| blockData NAME NEWLINE BLOCKS BLOCK_DATA_END- {% do { unitNameCheck $5 $2;- return $ PUBlockData () (getTransSpan $1 $5) (Just $2) (reverse $4) } }-| SUBPROGRAM_UNIT { $1 }--MAYBE_SUBPROGRAM_UNITS :: { Maybe [ ProgramUnit A0 ] }-: contains NEWLINE SUBPROGRAM_UNITS { Just $ reverse $3 }-| {- Empty -} { Nothing }--SUBPROGRAM_UNITS :: { [ ProgramUnit A0 ] }-: SUBPROGRAM_UNITS SUBPROGRAM_UNIT NEWLINE { $2 : $1 }-| {- EMPTY -} { [ ] }--SUBPROGRAM_UNIT :: { ProgramUnit A0 }-: PREFIXES function NAME MAYBE_ARGUMENTS MAYBE_RESULT MAYBE_COMMENT NEWLINE BLOCKS MAYBE_SUBPROGRAM_UNITS FUNCTION_END- {% do { unitNameCheck $10 $3;- let (pfxs, typeSpec) = case partitionEithers $1 of- { (ps, t:_) -> (fromReverseList' ps, Just t)- ; (ps, []) -> (fromReverseList' ps, Nothing) } in- let sfx = emptySuffixes in- let ss = if null $1 then getTransSpan $2 $10 else getTransSpan (reverse $1) $10 in- return $ PUFunction () ss typeSpec (pfxs, sfx) $3 $4 $5 (reverse $8) $9 } }-| PREFIXES subroutine NAME MAYBE_ARGUMENTS MAYBE_COMMENT NEWLINE BLOCKS MAYBE_SUBPROGRAM_UNITS SUBROUTINE_END- {% do { unitNameCheck $9 $3;- (pfxs, typeSpec) <- case partitionEithers $1 of- { (ps, t:_) -> fail "Subroutines cannot have return types."- ; (ps, []) -> return (fromReverseList' ps, Nothing) };- let sfx = emptySuffixes in- let ss = if null $1 then getTransSpan $2 $9 else getTransSpan (reverse $1) $9 in- return $ PUSubroutine () ss (pfxs, sfx) $3 $4 (reverse $7) $8 } }-| comment { let (TComment s c) = $1 in PUComment () s (Comment c) }---- (Fortran2003) R1227, Fortran95/90 (...)-PREFIXES :: { [Either (Prefix A0) (TypeSpec A0)] }-: PREFIXES PREFIX { $2:$1 }-| {- EMPTY -} { [] }---- (Fortran2003) R1228, Fortran95/90 (...)-PREFIX :: { Either (Prefix A0) (TypeSpec A0) }-: recursive { Left $ PfxRecursive () (getSpan $1) }-| TYPE_SPEC { Right $1 }--RESULT :: { Expression A0 }-: result '(' VARIABLE ')' { $3 }--MAYBE_RESULT :: { Maybe (Expression A0) }-: RESULT { Just $1 }-| {- empty -} { Nothing }--MAYBE_ARGUMENTS :: { Maybe (AList Expression A0) }-: '(' MAYBE_VARIABLES ')' { $2 }-| {- Nothing -} { Nothing }--PROGRAM_END :: { Token }-: end { $1 } | endProgram { $1 } | endProgram id { $2 }-MODULE_END :: { Token }-: end { $1 } | endModule { $1 } | endModule id { $2 }-FUNCTION_END :: { Token }-: end { $1 } | endFunction { $1 } | endFunction id { $2 }-SUBROUTINE_END :: { Token }-: end { $1 } | endSubroutine { $1 } | endSubroutine id { $2 }-BLOCK_DATA_END :: { Token }-: end { $1 } | endBlockData { $1 } | endBlockData id { $2 }-INTERFACE_END :: { Token }-: end { $1 } | endInterface { $1 } | endInterface id { $2 }--NAME :: { Name } : id { let (TId _ name) = $1 in name }--BLOCKS :: { [ Block A0 ] } : BLOCKS BLOCK { $2 : $1 } | {- EMPTY -} { [ ] }--BLOCK :: { Block A0 }-: IF_BLOCK MAYBE_COMMENT NEWLINE { $1 }-| CASE_BLOCK MAYBE_COMMENT NEWLINE { $1 }-| INTEGER_LITERAL STATEMENT MAYBE_COMMENT NEWLINE- { BlStatement () (getTransSpan $1 $2) (Just $1) $2 }-| STATEMENT MAYBE_COMMENT NEWLINE { BlStatement () (getSpan $1) Nothing $1 }-| interface MAYBE_EXPRESSION MAYBE_COMMENT NEWLINE SUBPROGRAM_UNITS2 MODULE_PROCEDURES INTERFACE_END MAYBE_COMMENT NEWLINE- { BlInterface () (getTransSpan $1 $9) $2 False (reverse $5) (reverse $6) }-| interface MAYBE_EXPRESSION MAYBE_COMMENT NEWLINE MODULE_PROCEDURES INTERFACE_END MAYBE_COMMENT NEWLINE- { BlInterface () (getTransSpan $1 $8) $2 False [ ] (reverse $5) }-| COMMENT_BLOCK { $1 }--IF_BLOCK :: { Block A0 }-: if '(' EXPRESSION ')' then MAYBE_COMMENT NEWLINE BLOCKS ELSE_BLOCKS- { let { startSpan = getSpan $1;- (endSpan, conds, blocks, endLabel) = $9;- span = getTransSpan startSpan endSpan }- in BlIf () span Nothing Nothing ((Just $3):conds) ((reverse $8):blocks) endLabel }-| id ':' if '(' EXPRESSION ')' then MAYBE_COMMENT NEWLINE BLOCKS ELSE_BLOCKS- { let { TId startSpan startName = $1;- (endSpan, conds, blocks, endLabel) = $11;- span = getTransSpan startSpan endSpan }- in BlIf () span Nothing (Just startName) ((Just $5):conds) ((reverse $10):blocks) endLabel }-| INTEGER_LITERAL if '(' EXPRESSION ')' then MAYBE_COMMENT NEWLINE BLOCKS ELSE_BLOCKS- { let { startSpan = getSpan $1;- startLabel = Just $1;- (endSpan, conds, blocks, endLabel) = $10;- span = getTransSpan startSpan endSpan }- in BlIf () span startLabel Nothing ((Just $4):conds) ((reverse $9):blocks) endLabel }-| INTEGER_LITERAL id ':' if '(' EXPRESSION ')' then MAYBE_COMMENT NEWLINE BLOCKS ELSE_BLOCKS- { let { startSpan = getSpan $1;- startLabel = Just $1;- TId _ startName = $2;- (endSpan, conds, blocks, endLabel) = $12;- span = getTransSpan startSpan endSpan }- in BlIf () span startLabel (Just startName) ((Just $6):conds) ((reverse $11):blocks) endLabel }--ELSE_BLOCKS :: { (SrcSpan, [Maybe (Expression A0)], [[Block A0]], Maybe (Expression A0)) }-: maybe(INTEGER_LITERAL) elsif '(' EXPRESSION ')' then MAYBE_COMMENT NEWLINE BLOCKS ELSE_BLOCKS- { let (endSpan, conds, blocks, endLabel) = $10- in (endSpan, Just $4 : conds, reverse $9 : blocks, endLabel) }-| maybe(INTEGER_LITERAL) else MAYBE_COMMENT NEWLINE BLOCKS END_IF- { let (endSpan, endLabel) = $6- in (endSpan, [Nothing], [reverse $5], endLabel) }-| END_IF { let (endSpan, endLabel) = $1 in (endSpan, [], [], endLabel) }--END_IF :: { (SrcSpan, Maybe (Expression A0)) }-: endif { (getSpan $1, Nothing) }-| endif id { (getSpan $2, Nothing) }-| INTEGER_LITERAL endif { (getSpan $2, Just $1) }-| INTEGER_LITERAL endif id { (getSpan $3, Just $1) }--CASE_BLOCK :: { Block A0 }-: selectcase '(' EXPRESSION ')' MAYBE_COMMENT NEWLINE CASES- { let { (caseRanges, blocks, endLabel, endSpan) = $7;- span = getTransSpan $1 endSpan }- in BlCase () span Nothing Nothing $3 caseRanges blocks endLabel }-| INTEGER_LITERAL selectcase '(' EXPRESSION ')' MAYBE_COMMENT NEWLINE CASES- { let { (caseRanges, blocks, endLabel, endSpan) = $8;- span = getTransSpan $1 endSpan }- in BlCase () span (Just $1) Nothing $4 caseRanges blocks endLabel }-| id ':' selectcase '(' EXPRESSION ')' MAYBE_COMMENT NEWLINE CASES- { let { (caseRanges, blocks, endLabel, endSpan) = $9;- TId s startName = $1;- span = getTransSpan s endSpan }- in BlCase () span Nothing (Just startName) $5 caseRanges blocks endLabel }-| INTEGER_LITERAL id ':' selectcase '(' EXPRESSION ')' MAYBE_COMMENT NEWLINE CASES- { let { (caseRanges, blocks, endLabel, endSpan) = $10;- TId s startName = $2;- span = getTransSpan s endSpan }- in BlCase () span (Just $1) (Just startName) $6 caseRanges blocks endLabel }---- We store line comments as statements, but this raises an issue: we have--- nowhere to place comments after a SELECT CASE but before a CASE. So we drop--- them. The inner CASES_ rule does /not/ use this, because comments can always--- be parsed as belonging to to the above CASE block.-CASES :: { ([Maybe (AList Index A0)], [[Block A0]], Maybe (Expression A0), SrcSpan) }-: COMMENT_BLOCK CASES_ { $2 }-| CASES_ { $1 }--CASES_ :: { ([Maybe (AList Index A0)], [[Block A0]], Maybe (Expression A0), SrcSpan) }-: maybe(INTEGER_LITERAL) case '(' INDICIES ')' MAYBE_COMMENT NEWLINE BLOCKS CASES_- { let (scrutinees, blocks, endLabel, endSpan) = $9- in (Just (fromReverseList $4) : scrutinees, reverse $8 : blocks, endLabel, endSpan) }-| maybe(INTEGER_LITERAL) case default MAYBE_COMMENT NEWLINE BLOCKS END_SELECT- { let (endLabel, endSpan) = $7- in ([Nothing], [$6], endLabel, endSpan) }-| END_SELECT- { let (endLabel, endSpan) = $1- in ([], [], endLabel, endSpan) }--END_SELECT :: { (Maybe (Expression A0), SrcSpan) }-: maybe(INTEGER_LITERAL) endselect maybe(id)- { ($1, maybe (getSpan $2) getSpan $3) }--MAYBE_EXPRESSION :: { Maybe (Expression A0) }-: EXPRESSION { Just $1 }-| {- EMPTY -} { Nothing }--MAYBE_COMMENT :: { Maybe Token }-: comment { Just $1 }-| {- EMPTY -} { Nothing }--SUBPROGRAM_UNITS2 :: { [ ProgramUnit A0 ] }-: SUBPROGRAM_UNITS SUBPROGRAM_UNIT NEWLINE { $2 : $1 }--MODULE_PROCEDURES :: { [ Block A0 ] }-: MODULE_PROCEDURES MODULE_PROCEDURE { $2 : $1 }-| MODULE_PROCEDURES MODULE_PROCEDURE COMMENT_BLOCK { $3 : $2 : $1 }-| { [ ] }--MODULE_PROCEDURE :: { Block A0 }-: moduleProcedure VARIABLES MAYBE_COMMENT NEWLINE- { let { al = fromReverseList $2;- st = StModuleProcedure () (getTransSpan $1 al) (fromReverseList $2) }- in BlStatement () (getTransSpan $1 $4) Nothing st }--COMMENT_BLOCK :: { Block A0 }-: comment NEWLINE { let (TComment s c) = $1 in BlComment () s (Comment c) }--MAYBE_NEWLINE :: { Maybe Token } : NEWLINE { Just $1 } | {- EMPTY -} { Nothing }--NEWLINE :: { Token }-: NEWLINE newline { $1 }-| NEWLINE ';' { $1 }-| newline { $1 }-| ';' { $1 }--STATEMENT :: { Statement A0 }-: NONEXECUTABLE_STATEMENT { $1 }-| EXECUTABLE_STATEMENT { $1 }--EXPRESSION_ASSIGNMENT_STATEMENT :: { Statement A0 }-: DATA_REF '=' EXPRESSION { StExpressionAssign () (getTransSpan $1 $3) $1 $3 }--NONEXECUTABLE_STATEMENT :: { Statement A0 }-: DECLARATION_STATEMENT { $1 }-| intent '(' INTENT_CHOICE ')' MAYBE_DCOLON EXPRESSION_LIST- { let expAList = fromReverseList $6- in StIntent () (getTransSpan $1 expAList) $3 expAList }-| optional MAYBE_DCOLON EXPRESSION_LIST- { let expAList = fromReverseList $3- in StOptional () (getTransSpan $1 expAList) expAList }-| public MAYBE_DCOLON EXPRESSION_LIST- { let expAList = fromReverseList $3- in StPublic () (getTransSpan $1 expAList) (Just expAList) }-| public { StPublic () (getSpan $1) Nothing }-| private MAYBE_DCOLON EXPRESSION_LIST- { let expAList = fromReverseList $3- in StPrivate () (getTransSpan $1 expAList) (Just expAList) }-| private { StPrivate () (getSpan $1) Nothing }-| save MAYBE_DCOLON SAVE_ARGS- { let saveAList = (fromReverseList $3)- in StSave () (getTransSpan $1 saveAList) (Just saveAList) }-| save { StSave () (getSpan $1) Nothing }-| dimension MAYBE_DCOLON INITIALIZED_DECLARATOR_LIST- { let declAList = fromReverseList $3- in StDimension () (getTransSpan $1 declAList) declAList }-| allocatable MAYBE_DCOLON INITIALIZED_DECLARATOR_LIST- { let declAList = fromReverseList $3- in StAllocatable () (getTransSpan $1 declAList) declAList }-| pointer MAYBE_DCOLON INITIALIZED_DECLARATOR_LIST- { let declAList = fromReverseList $3- in StPointer () (getTransSpan $1 declAList) declAList }-| target MAYBE_DCOLON INITIALIZED_DECLARATOR_LIST- { let declAList = fromReverseList $3- in StTarget () (getTransSpan $1 declAList) declAList }-| data cDATA DATA_GROUPS cPOP- { let dataAList = fromReverseList $3- in StData () (getTransSpan $1 dataAList) dataAList }-| parameter '(' PARAMETER_ASSIGNMENTS ')'- { let declAList = fromReverseList $3- in StParameter () (getTransSpan $1 $4) declAList }-| implicit none { StImplicit () (getTransSpan $1 $2) Nothing }-| implicit cIMPLICIT IMP_LISTS cPOP- { let impAList = fromReverseList $3- in StImplicit () (getTransSpan $1 impAList) $ Just $ impAList }-| namelist cNAMELIST NAMELISTS cPOP- { let nameALists = fromReverseList $3- in StNamelist () (getTransSpan $1 nameALists) nameALists }-| equivalence EQUIVALENCE_GROUPS- { let eqALists = fromReverseList $2- in StEquivalence () (getTransSpan $1 eqALists) eqALists }-| common cCOMMON COMMON_GROUPS cPOP- { let commonAList = fromReverseList $3- in StCommon () (getTransSpan $1 commonAList) commonAList }-| external MAYBE_DCOLON VARIABLES- { let alist = fromReverseList $3- in StExternal () (getTransSpan $1 alist) alist }-| intrinsic MAYBE_DCOLON VARIABLES- { let alist = fromReverseList $3- in StIntrinsic () (getTransSpan $1 alist) alist }-| use VARIABLE { StUse () (getTransSpan $1 $2) $2 Nothing Permissive Nothing }-| use VARIABLE ',' RENAME_LIST- { let alist = fromReverseList $4- in StUse () (getTransSpan $1 alist) $2 Nothing Permissive (Just alist) }-| use VARIABLE ',' only ':' MAYBE_RENAME_LIST- { StUse () (getTransSpan $1 ($5, $6)) $2 Nothing Exclusive $6 }-| entry VARIABLE MAYBE_RESULT- { StEntry () (getTransSpan $1 $ maybe (getSpan $2) getSpan $3) $2 Nothing $3 }-| entry VARIABLE '(' ')' MAYBE_RESULT- { StEntry () (getTransSpan $1 $ maybe (getSpan $4) getSpan $5) $2 Nothing $5 }-| entry VARIABLE '(' VARIABLES ')' MAYBE_RESULT- { StEntry () (getTransSpan $1 $ maybe (getSpan $5) getSpan $6) $2 (Just $ fromReverseList $4) $6 }-| sequence { StSequence () (getSpan $1) }-| type ATTRIBUTE_LIST '::' id- { let { TId span id = $4;- alist = if null $2 then Nothing else (Just . fromReverseList) $2 }- in StType () (getTransSpan $1 span) alist id }-| type id- { let TId span id = $2 in StType () (getTransSpan $1 span) Nothing id }-| endType { StEndType () (getSpan $1) Nothing }-| endType id- { let TId span id = $2 in StEndType () (getTransSpan $1 span) (Just id) }-| include STRING { StInclude () (getTransSpan $1 $2) $2 Nothing }--- Following is a fake node to make arbitrary FORMAT statements parsable.--- Must be fixed in the future. TODO-| format blob- { let TBlob s blob = $2 in StFormatBogus () (getTransSpan $1 s) blob }--EXECUTABLE_STATEMENT :: { Statement A0 }-: allocate '(' DATA_REFS MAYBE_ALLOC_OPT_LIST ')'- { StAllocate () (getTransSpan $1 $5) Nothing (fromReverseList $3) $4 }-| nullify '(' DATA_REFS ')'- { StNullify () (getTransSpan $1 $4) (fromReverseList $3) }-| deallocate '(' DATA_REFS MAYBE_ALLOC_OPT_LIST ')'- { StDeallocate () (getTransSpan $1 $5) (fromReverseList $3) $4 }-| EXPRESSION_ASSIGNMENT_STATEMENT { $1 }-| DATA_REF '=>' EXPRESSION { StPointerAssign () (getTransSpan $1 $3) $1 $3 }-| where '(' EXPRESSION ')' EXPRESSION_ASSIGNMENT_STATEMENT- { StWhere () (getTransSpan $1 $5) $3 $5 }-| where '(' EXPRESSION ')' { StWhereConstruct () (getTransSpan $1 $4) Nothing $3 }-| elsewhere '(' EXPRESSION ')' { StElsewhere () (getTransSpan $1 $4) Nothing (Just $3) }-| elsewhere { StElsewhere () (getSpan $1) Nothing Nothing }-| endwhere { StEndWhere () (getSpan $1) Nothing }-| if '(' EXPRESSION ')' INTEGER_LITERAL ',' INTEGER_LITERAL ',' INTEGER_LITERAL- { StIfArithmetic () (getTransSpan $1 $9) $3 $5 $7 $9 }-| do { StDo () (getSpan $1) Nothing Nothing Nothing }-| id ':' do- { let TId s id = $1- in StDo () (getTransSpan s $3) (Just id) Nothing Nothing }-| do INTEGER_LITERAL MAYBE_COMMA DO_SPECIFICATION- { StDo () (getTransSpan $1 $4) Nothing (Just $2) (Just $4) }-| do DO_SPECIFICATION { StDo () (getTransSpan $1 $2) Nothing Nothing (Just $2) }-| id ':' do DO_SPECIFICATION- { let TId s id = $1- in StDo () (getTransSpan s $4) (Just id) Nothing (Just $4) }-| do INTEGER_LITERAL MAYBE_COMMA while '(' EXPRESSION ')'- { StDoWhile () (getTransSpan $1 $7) Nothing (Just $2) $6 }-| do while '(' EXPRESSION ')'- { StDoWhile () (getTransSpan $1 $5) Nothing Nothing $4 }-| id ':' do while '(' EXPRESSION ')'- { let TId s id = $1- in StDoWhile () (getTransSpan s $7) (Just id) Nothing $6 }-| enddo { StEnddo () (getSpan $1) Nothing }-| enddo id- { let TId s id = $2 in StEnddo () (getTransSpan $1 s) (Just id) }-| cycle { StCycle () (getSpan $1) Nothing }-| cycle VARIABLE { StCycle () (getTransSpan $1 $2) (Just $2) }-| exit { StExit () (getSpan $1) Nothing }-| exit VARIABLE { StExit () (getTransSpan $1 $2) (Just $2) }--- GO TO label-| goto INTEGER_LITERAL { StGotoUnconditional () (getTransSpan $1 $2) $2 }--- GO TO scalar-int-variable-| goto VARIABLE { StGotoUnconditional () (getTransSpan $1 $2) $2 }--- GO TO scalar-int-variable [,] label-list-| goto VARIABLE MAYBE_COMMA '(' INTEGERS ')'- { StGotoAssigned () (getTransSpan $1 $6) $2 (Just (fromReverseList $5)) }--- GO TO label-list [,] scalar-int-expression-| goto '(' INTEGERS ')' MAYBE_COMMA EXPRESSION- { StGotoComputed () (getTransSpan $1 $6) (fromReverseList $3) $6 }-| assign INTEGER_LITERAL to VARIABLE- { StLabelAssign () (getTransSpan $1 $4) $2 $4 }-| continue { StContinue () (getSpan $1) }-| stop { StStop () (getSpan $1) Nothing }-| stop EXPRESSION { StStop () (getTransSpan $1 $2) (Just $2) }-| pause { StPause () (getSpan $1) Nothing }-| pause EXPRESSION { StPause () (getTransSpan $1 $2) (Just $2) }-| if '(' EXPRESSION ')' EXECUTABLE_STATEMENT- { StIfLogical () (getTransSpan $1 $5) $3 $5 }-| read CILIST IN_IOLIST- { let alist = fromReverseList $3- in StRead () (getTransSpan $1 alist) $2 (Just alist) }-| read CILIST { StRead () (getTransSpan $1 $2) $2 Nothing }-| read FORMAT_ID ',' IN_IOLIST- { let alist = fromReverseList $4- in StRead2 () (getTransSpan $1 alist) $2 (Just alist) }-| read FORMAT_ID { StRead2 () (getTransSpan $1 $2) $2 Nothing }-| write CILIST OUT_IOLIST- { let alist = fromReverseList $3- in StWrite () (getTransSpan $1 alist) $2 (Just alist) }-| write CILIST { StWrite () (getTransSpan $1 $2) $2 Nothing }-| print FORMAT_ID ',' OUT_IOLIST- { let alist = fromReverseList $4- in StPrint () (getTransSpan $1 alist) $2 (Just alist) }-| print FORMAT_ID { StPrint () (getTransSpan $1 $2) $2 Nothing }-| open CILIST { StOpen () (getTransSpan $1 $2) $2 }-| close CILIST { StClose () (getTransSpan $1 $2) $2 }-| inquire CILIST { StInquire () (getTransSpan $1 $2) $2 }-| rewind CILIST { StRewind () (getTransSpan $1 $2) $2 }-| rewind UNIT { StRewind2 () (getTransSpan $1 $2) $2 }-| endfile CILIST { StEndfile () (getTransSpan $1 $2) $2 }-| endfile UNIT { StEndfile2 () (getTransSpan $1 $2) $2 }-| backspace CILIST { StBackspace () (getTransSpan $1 $2) $2 }-| backspace UNIT { StBackspace2 () (getTransSpan $1 $2) $2 }-| call VARIABLE { StCall () (getTransSpan $1 $2) $2 Nothing }-| call VARIABLE '(' ')' { StCall () (getTransSpan $1 $4) $2 Nothing }-| call VARIABLE '(' ARGUMENTS ')'- { let alist = fromReverseList $4- in StCall () (getTransSpan $1 $5) $2 (Just alist) }-| return { StReturn () (getSpan $1) Nothing }-| return EXPRESSION { StReturn () (getTransSpan $1 $2) (Just $2) }--ARGUMENTS :: { [ Argument A0 ] }-: ARGUMENTS ',' ARGUMENT { $3 : $1 }-| ARGUMENT { [ $1 ] }--ARGUMENT :: { Argument A0 }-: id '=' EXPRESSION- { let TId span keyword = $1- in Argument () (getTransSpan span $3) (Just keyword) $3 }-| EXPRESSION- { Argument () (getSpan $1) Nothing $1 }--MAYBE_RENAME_LIST :: { Maybe (AList Use A0) }-: RENAME_LIST { Just $ fromReverseList $1 }-| {- empty -} { Nothing }--RENAME_LIST :: { [ Use A0 ] }-: RENAME_LIST ',' RENAME { $3 : $1 }-| RENAME { [ $1 ] }--RENAME :: { Use A0 }-: VARIABLE '=>' VARIABLE { UseRename () (getTransSpan $1 $3) $1 $3 }-| VARIABLE { UseID () (getSpan $1) $1 }-| operator '(' opCustom ')'- { let TOpCustom ss op = $3- in UseID () (getTransSpan $1 $4) (ExpValue () ss (ValOperator op)) }-| assignment { UseID () (getSpan $1) (ExpValue () (getSpan $1) ValAssignment) }--MAYBE_DCOLON :: { () } : '::' { () } | {- EMPTY -} { () }--FORMAT_ID :: { Expression A0 }-: FORMAT_ID '/' '/' FORMAT_ID %prec CONCAT- { ExpBinary () (getTransSpan $1 $4) Concatenation $1 $4 }-| INTEGER_LITERAL { $1 }-| STRING { $1 }-| DATA_REF { $1 }-| '*' { ExpValue () (getSpan $1) ValStar }--UNIT :: { Expression A0 }-: INTEGER_LITERAL { $1 }-| DATA_REF { $1 }-| '*' { ExpValue () (getSpan $1) ValStar }--CILIST :: { AList ControlPair A0 }-: '(' CILIST_ELEMENT ',' FORMAT_ID ',' CILIST_PAIRS ')'- { let { cp1 = ControlPair () (getSpan $2) Nothing $2;- cp2 = ControlPair () (getSpan $4) Nothing $4;- tail = fromReverseList $6 }- in setSpan (getTransSpan $1 $7) $ cp1 `aCons` cp2 `aCons` tail }-| '(' CILIST_ELEMENT ',' FORMAT_ID ')'- { let { cp1 = ControlPair () (getSpan $2) Nothing $2;- cp2 = ControlPair () (getSpan $4) Nothing $4 }- in AList () (getTransSpan $1 $5) [ cp1, cp2 ] }-| '(' CILIST_ELEMENT ',' CILIST_PAIRS ')'- { let { cp1 = ControlPair () (getSpan $2) Nothing $2;- tail = fromReverseList $4 }- in setSpan (getTransSpan $1 $5) $ cp1 `aCons` tail }-| '(' CILIST_ELEMENT ')'- { let cp1 = ControlPair () (getSpan $2) Nothing $2- in AList () (getTransSpan $1 $3) [ cp1 ] }-| '(' CILIST_PAIRS ')' { fromReverseList $2 }--CILIST_PAIRS :: { [ ControlPair A0 ] }-: CILIST_PAIRS ',' CILIST_PAIR { $3 : $1 }-| CILIST_PAIR { [ $1 ] }--CILIST_PAIR :: { ControlPair A0 }-: id '=' CILIST_ELEMENT- { let (TId s id) = $1 in ControlPair () (getTransSpan s $3) (Just id) $3 }--CILIST_ELEMENT :: { Expression A0 }-: CI_EXPRESSION { $1 }-| '*' { ExpValue () (getSpan $1) ValStar }--CI_EXPRESSION :: { Expression A0 }-: CI_EXPRESSION '+' CI_EXPRESSION- { ExpBinary () (getTransSpan $1 $3) Addition $1 $3 }-| CI_EXPRESSION '-' CI_EXPRESSION- { ExpBinary () (getTransSpan $1 $3) Subtraction $1 $3 }-| CI_EXPRESSION '*' CI_EXPRESSION- { ExpBinary () (getTransSpan $1 $3) Multiplication $1 $3 }-| CI_EXPRESSION '/' CI_EXPRESSION- { ExpBinary () (getTransSpan $1 $3) Division $1 $3 }-| CI_EXPRESSION '**' CI_EXPRESSION- { ExpBinary () (getTransSpan $1 $3) Exponentiation $1 $3 }-| CI_EXPRESSION '/' '/' CI_EXPRESSION %prec CONCAT- { ExpBinary () (getTransSpan $1 $4) Concatenation $1 $4 }-| ARITHMETIC_SIGN CI_EXPRESSION %prec SIGN- { ExpUnary () (getTransSpan (fst $1) $2) (snd $1) $2 }-| CI_EXPRESSION or CI_EXPRESSION- { ExpBinary () (getTransSpan $1 $3) Or $1 $3 }-| CI_EXPRESSION and CI_EXPRESSION- { ExpBinary () (getTransSpan $1 $3) And $1 $3 }-| not CI_EXPRESSION- { ExpUnary () (getTransSpan $1 $2) Not $2 }-| CI_EXPRESSION eqv CI_EXPRESSION- { ExpBinary () (getTransSpan $1 $3) Equivalent $1 $3 }-| CI_EXPRESSION neqv CI_EXPRESSION- { ExpBinary () (getTransSpan $1 $3) NotEquivalent $1 $3 }-| CI_EXPRESSION RELATIONAL_OPERATOR CI_EXPRESSION %prec RELATIONAL- { ExpBinary () (getTransSpan $1 $3) $2 $1 $3 }-| opCustom CI_EXPRESSION %prec DEFINED_UNARY- { let TOpCustom span str = $1- in ExpUnary () (getTransSpan span $2) (UnCustom str) $2 }-| CI_EXPRESSION opCustom CI_EXPRESSION- { let TOpCustom _ str = $2- in ExpBinary () (getTransSpan $1 $3) (BinCustom str) $1 $3 }-| '(' CI_EXPRESSION ')' { setSpan (getTransSpan $1 $3) $2 }-| INTEGER_LITERAL { $1 }-| LOGICAL_LITERAL { $1 }-| STRING { $1 }-| DATA_REF { $1 }--MAYBE_ALLOC_OPT_LIST :: { Maybe (AList AllocOpt A0) }-: ',' stat '=' EXPRESSION { Just (fromReverseList [AOStat () (getTransSpan $2 $4) $4]) }-| {- empty -} { Nothing }--IN_IOLIST :: { [ Expression A0 ] }-: IN_IOLIST ',' IN_IO_ELEMENT { $3 : $1}-| IN_IO_ELEMENT { [ $1 ] }--IN_IO_ELEMENT :: { Expression A0 }-: DATA_REF { $1 }-| '(' IN_IOLIST ',' DO_SPECIFICATION ')'- { ExpImpliedDo () (getTransSpan $1 $5) (fromReverseList $2) $4 }--OUT_IOLIST :: { [ Expression A0 ] }-: OUT_IOLIST ',' EXPRESSION { $3 : $1}-| EXPRESSION { [ $1 ] }--COMMON_GROUPS :: { [ CommonGroup A0 ] }-: COMMON_GROUPS COMMON_GROUP { $2 : $1 }-| COMMON_GROUPS ',2' COMMON_GROUP { $3 : $1 }-| INIT_COMMON_GROUP { [ $1 ] }--COMMON_GROUP :: { CommonGroup A0 }-: COMMON_NAME UNINITIALIZED_DECLARATOR_LIST- { let alist = fromReverseList $2- in CommonGroup () (getTransSpan $1 alist) (Just $1) alist }-| '/' '/' UNINITIALIZED_DECLARATOR_LIST- { let alist = fromReverseList $3- in CommonGroup () (getTransSpan $1 alist) Nothing alist }--INIT_COMMON_GROUP :: { CommonGroup A0 }-: COMMON_NAME UNINITIALIZED_DECLARATOR_LIST- { let alist = fromReverseList $2- in CommonGroup () (getTransSpan $1 alist) (Just $1) alist }-| '/' '/' UNINITIALIZED_DECLARATOR_LIST- { let alist = fromReverseList $3- in CommonGroup () (getTransSpan $1 alist) Nothing alist }-| UNINITIALIZED_DECLARATOR_LIST- { let alist = fromReverseList $1- in CommonGroup () (getSpan alist) Nothing alist }--EQUIVALENCE_GROUPS :: { [ AList Expression A0 ] }-: EQUIVALENCE_GROUPS ',' '(' PART_REFS ')'- { setSpan (getTransSpan $3 $5) (fromReverseList $4) : $1 }-| '(' PART_REFS ')'- { [ setSpan (getTransSpan $1 $3) (fromReverseList $2) ] }--NAMELISTS :: { [ Namelist A0 ] }-: NAMELISTS NAMELIST { $2 : $1 }-| NAMELISTS ',2' NAMELIST { $3 : $1 }-| NAMELIST { [ $1 ] }--NAMELIST :: { Namelist A0 }-: '/' VARIABLE '/' VARIABLES- { Namelist () (getTransSpan $1 $4) $2 $ fromReverseList $4 }--MAYBE_VARIABLES :: { Maybe (AList Expression A0) }-: VARIABLES { Just $ fromReverseList $1 } | {- EMPTY -} { Nothing }--VARIABLES :: { [ Expression A0 ] }-: VARIABLES ',' VARIABLE { $3 : $1 }-| VARIABLE { [ $1 ] }--IMP_LISTS :: { [ ImpList A0 ] }-: IMP_LISTS ',' IMP_LIST { $3 : $1 }-| IMP_LIST { [ $1 ] }--IMP_LIST :: { ImpList A0 }-: TYPE_SPEC '(2' IMP_ELEMENTS ')'- { ImpList () (getTransSpan $1 $4) $1 (aReverse $3) }--IMP_ELEMENTS :: { AList ImpElement A0 }-: IMP_ELEMENTS ',' IMP_ELEMENT { setSpan (getTransSpan $1 $3) $ $3 `aCons` $1 }-| IMP_ELEMENT { AList () (getSpan $1) [ $1 ] }--IMP_ELEMENT :: { ImpElement A0 }-: id {% do- let (TId s id) = $1- if length id /= 1- then fail "Implicit argument must be a character."- else return $ ImpCharacter () s id- }-| id '-' id {% do- let (TId _ id1) = $1- let (TId _ id2) = $3- if length id1 /= 1 || length id2 /= 1- then fail "Implicit argument must be a character."- else return $ ImpRange () (getTransSpan $1 $3) id1 id2- }--PARAMETER_ASSIGNMENTS :: { [ Declarator A0 ] }-: PARAMETER_ASSIGNMENTS ',' PARAMETER_ASSIGNMENT { $3 : $1 }-| PARAMETER_ASSIGNMENT { [ $1 ] }--PARAMETER_ASSIGNMENT :: { Declarator A0 }-: VARIABLE '=' EXPRESSION- { Declarator () (getTransSpan $1 $3) $1 ScalarDecl Nothing (Just $3) }--DECLARATION_STATEMENT :: { Statement A0 }-: TYPE_SPEC ATTRIBUTE_LIST '::' INITIALIZED_DECLARATOR_LIST- { let { mAttrAList = if null $2 then Nothing else Just $ fromReverseList $2;- declAList = fromReverseList $4 }- in StDeclaration () (getTransSpan $1 declAList) $1 mAttrAList declAList }-| TYPE_SPEC INITIALIZED_DECLARATOR_LIST- { let { declAList = fromReverseList $2 }- in StDeclaration () (getTransSpan $1 declAList) $1 Nothing declAList }--ATTRIBUTE_LIST :: { [ Attribute A0 ] }-: ATTRIBUTE_LIST ',' ATTRIBUTE_SPEC { $3 : $1 }-| {- EMPTY -} { [ ] }--ATTRIBUTE_SPEC :: { Attribute A0 }-: public { AttrPublic () (getSpan $1) }-| private { AttrPrivate () (getSpan $1) }-| allocatable { AttrAllocatable () (getSpan $1) }-| dimension '(' DIMENSION_DECLARATORS ')'- { AttrDimension () (getTransSpan $1 $4) (aReverse $3) }-| external { AttrExternal () (getSpan $1) }-| intent '(' INTENT_CHOICE ')' { AttrIntent () (getTransSpan $1 $4) $3 }-| intrinsic { AttrIntrinsic () (getSpan $1) }-| optional { AttrOptional () (getSpan $1) }-| pointer { AttrPointer () (getSpan $1) }-| parameter { AttrParameter () (getSpan $1) }-| save { AttrSave () (getSpan $1) }-| target { AttrTarget () (getSpan $1) }--INTENT_CHOICE :: { Intent } : in { In } | out { Out } | inout { InOut }--DATA_GROUPS :: { [ DataGroup A0 ] }-: DATA_GROUPS MAYBE_COMMA DATA_LIST slash EXPRESSION_LIST slash- { let { nameAList = fromReverseList $3;- dataAList = fromReverseList $5 }- in DataGroup () (getTransSpan nameAList $6) nameAList dataAList : $1 }-| DATA_LIST slash EXPRESSION_LIST slash- { let { nameAList = fromReverseList $1;- dataAList = fromReverseList $3 }- in [ DataGroup () (getTransSpan nameAList $4) nameAList dataAList ] }--MAYBE_COMMA :: { () } : ',' { () } | {- EMPTY -} { () }--DATA_LIST :: { [ Expression A0 ] }-: DATA_LIST ',' DATA_ELEMENT { $3 : $1 }-| DATA_ELEMENT { [ $1 ] }--DATA_ELEMENT :: { Expression A0 }-: DATA_REF { $1 } | IMPLIED_DO { $1 }--SAVE_ARGS :: { [ Expression A0 ] }-: SAVE_ARGS ',' SAVE_ARG { $3 : $1 } | SAVE_ARG { [ $1 ] }--SAVE_ARG :: { Expression A0 } : COMMON_NAME { $1 } | VARIABLE { $1 }--COMMON_NAME :: { Expression A0 }-: '/' VARIABLE '/' { setSpan (getTransSpan $1 $3) $2 }--INITIALIZED_DECLARATOR_LIST :: { [ Declarator A0 ] }-: INITIALIZED_DECLARATOR_LIST ',' INITIALIZED_DECLARATOR { $3 : $1 }-| INITIALIZED_DECLARATOR { [ $1 ] }--UNINITIALIZED_DECLARATOR_LIST :: { [ Declarator A0 ] }-: UNINITIALIZED_DECLARATOR_LIST ',' DECLARATOR { $3 : $1 }-| DECLARATOR { [ $1 ] }--INITIALIZED_DECLARATOR :: { Declarator A0 }-: DECLARATOR '=' EXPRESSION { setInitialisation $1 $3 }-| DECLARATOR '=>' EXPRESSION { setInitialisation $1 $3 }-| DECLARATOR { $1 }--DECLARATOR :: { Declarator A0 }-: VARIABLE- { Declarator () (getSpan $1) $1 ScalarDecl Nothing Nothing }-| VARIABLE '*' EXPRESSION- { Declarator () (getTransSpan $1 $3) $1 ScalarDecl (Just $3) Nothing }-| VARIABLE '*' '(' '*' ')'- { let star = ExpValue () (getSpan $4) ValStar- in Declarator () (getTransSpan $1 $5) $1 ScalarDecl (Just star) Nothing }-| VARIABLE '(' DIMENSION_DECLARATORS ')'- { Declarator () (getTransSpan $1 $4) $1 (ArrayDecl (aReverse $3)) Nothing Nothing }-| VARIABLE '(' DIMENSION_DECLARATORS ')' '*' EXPRESSION- { Declarator () (getTransSpan $1 $6) $1 (ArrayDecl (aReverse $3)) (Just $6) Nothing }--- nonstandard char array syntax (wrong order for dimensions & charlen)-| VARIABLE '*' EXPRESSION '(' DIMENSION_DECLARATORS ')'- { Declarator () (getTransSpan $1 $6) $1 (ArrayDecl (aReverse $5)) (Just $3) Nothing }-| VARIABLE '(' DIMENSION_DECLARATORS ')' '*' '(' '*' ')'- { let star = ExpValue () (getSpan $7) ValStar- in Declarator () (getTransSpan $1 $8) $1 (ArrayDecl (aReverse $3)) (Just star) Nothing }--DIMENSION_DECLARATORS :: { AList DimensionDeclarator A0 }-: DIMENSION_DECLARATORS ',' DIMENSION_DECLARATOR- { setSpan (getTransSpan $1 $3) $ $3 `aCons` $1 }-| DIMENSION_DECLARATOR- { AList () (getSpan $1) [ $1 ] }--DIMENSION_DECLARATOR :: { DimensionDeclarator A0 }-: EXPRESSION ':' EXPRESSION- { DimensionDeclarator () (getTransSpan $1 $3) (Just $1) (Just $3) }-| EXPRESSION { DimensionDeclarator () (getSpan $1) Nothing (Just $1) }--- Lower bound only-| EXPRESSION ':'- { DimensionDeclarator () (getTransSpan $1 $2) (Just $1) Nothing }-| EXPRESSION ':' '*'- { let { span = getSpan $3;- star = ExpValue () span ValStar }- in DimensionDeclarator () (getTransSpan $1 span) (Just $1) (Just star) }-| '*'- { let { span = getSpan $1;- star = ExpValue () span ValStar }- in DimensionDeclarator () span Nothing (Just star) }-| ':'- { let span = getSpan $1- in DimensionDeclarator () span Nothing Nothing }--TYPE_SPEC :: { TypeSpec A0 }-: integer KIND_SELECTOR { TypeSpec () (getSpan ($1, $2)) TypeInteger $2 }-| real KIND_SELECTOR { TypeSpec () (getSpan ($1, $2)) TypeReal $2 }-| doublePrecision { TypeSpec () (getSpan $1) TypeDoublePrecision Nothing }-| complex KIND_SELECTOR { TypeSpec () (getSpan ($1, $2)) TypeComplex $2 }-| character CHAR_SELECTOR { TypeSpec () (getSpan ($1, $2)) TypeCharacter $2 }-| logical KIND_SELECTOR { TypeSpec () (getSpan ($1, $2)) TypeLogical $2 }-| type '(' id ')'- { let TId _ id = $3- in TypeSpec () (getTransSpan $1 $4) (TypeCustom id) Nothing }--KIND_SELECTOR :: { Maybe (Selector A0) }-: '(' EXPRESSION ')'- { Just $ Selector () (getTransSpan $1 $3) Nothing (Just $2) }-| '(' kind '=' EXPRESSION ')'- { Just $ Selector () (getTransSpan $1 $5) Nothing (Just $4) }-| '*' EXPRESSION -- non-standard but commonly used extension- { Just $ Selector () (getTransSpan $1 $2) Nothing (Just $2) }-| {- EMPTY -} { Nothing }--CHAR_SELECTOR :: { Maybe (Selector A0) }-: '*' EXPRESSION- { Just $ Selector () (getTransSpan $1 $2) (Just $2) Nothing }--- The following rule is a bug in the spec.--- | '*' EXPRESSION ','--- { Just $ Selector () (getTransSpan $1 $2) (Just $2) Nothing }-| '*' '(' '*' ')'- { let star = ExpValue () (getSpan $3) ValStar- in Just $ Selector () (getTransSpan $1 $4) (Just star) Nothing }-| '(' LEN_EXPRESSION ')'- { Just $ Selector () (getTransSpan $1 $3) (Just $2) Nothing }-| '(' len '=' LEN_EXPRESSION ')'- { Just $ Selector () (getTransSpan $1 $5) (Just $4) Nothing }-| '(' kind '=' EXPRESSION ')'- { Just $ Selector () (getTransSpan $1 $5) Nothing (Just $4) }-| '(' LEN_EXPRESSION ',' EXPRESSION ')'- { Just $ Selector () (getTransSpan $1 $5) (Just $2) (Just $4) }-| '(' LEN_EXPRESSION ',' kind '=' EXPRESSION ')'- { Just $ Selector () (getTransSpan $1 $7) (Just $2) (Just $6) }-| '(' len '=' LEN_EXPRESSION ',' kind '=' EXPRESSION ')'- { Just $ Selector () (getTransSpan $1 $9) (Just $4) (Just $8) }-| '(' kind '=' EXPRESSION ',' len '=' LEN_EXPRESSION ')'- { Just $ Selector () (getTransSpan $1 $9) (Just $8) (Just $4) }-| {- EMPTY -} { Nothing }--LEN_EXPRESSION :: { Expression A0 }-: EXPRESSION { $1 }-| '*' { ExpValue () (getSpan $1) ValStar }--EXPRESSION :: { Expression A0 }-: EXPRESSION '+' EXPRESSION- { ExpBinary () (getTransSpan $1 $3) Addition $1 $3 }-| EXPRESSION '-' EXPRESSION- { ExpBinary () (getTransSpan $1 $3) Subtraction $1 $3 }-| EXPRESSION '*' EXPRESSION- { ExpBinary () (getTransSpan $1 $3) Multiplication $1 $3 }-| EXPRESSION '/' EXPRESSION- { ExpBinary () (getTransSpan $1 $3) Division $1 $3 }-| EXPRESSION '**' EXPRESSION- { ExpBinary () (getTransSpan $1 $3) Exponentiation $1 $3 }-| EXPRESSION '/' '/' EXPRESSION %prec CONCAT- { ExpBinary () (getTransSpan $1 $4) Concatenation $1 $4 }-| ARITHMETIC_SIGN EXPRESSION %prec SIGN- { ExpUnary () (getTransSpan (fst $1) $2) (snd $1) $2 }-| EXPRESSION or EXPRESSION- { ExpBinary () (getTransSpan $1 $3) Or $1 $3 }-| EXPRESSION and EXPRESSION- { ExpBinary () (getTransSpan $1 $3) And $1 $3 }-| not EXPRESSION- { ExpUnary () (getTransSpan $1 $2) Not $2 }-| EXPRESSION eqv EXPRESSION- { ExpBinary () (getTransSpan $1 $3) Equivalent $1 $3 }-| EXPRESSION neqv EXPRESSION- { ExpBinary () (getTransSpan $1 $3) NotEquivalent $1 $3 }-| EXPRESSION RELATIONAL_OPERATOR EXPRESSION %prec RELATIONAL- { ExpBinary () (getTransSpan $1 $3) $2 $1 $3 }-| opCustom EXPRESSION %prec DEFINED_UNARY- { let TOpCustom span str = $1- in ExpUnary () (getTransSpan span $2) (UnCustom str) $2 }-| EXPRESSION opCustom EXPRESSION- { let TOpCustom _ str = $2- in ExpBinary () (getTransSpan $1 $3) (BinCustom str) $1 $3 }-| '(' EXPRESSION ')' { setSpan (getTransSpan $1 $3) $2 }-| NUMERIC_LITERAL { $1 }-| '(' EXPRESSION ',' EXPRESSION ')'- { ExpValue () (getTransSpan $1 $5) (ValComplex $2 $4) }-| LOGICAL_LITERAL { $1 }-| STRING { $1 }-| DATA_REF { $1 }-| IMPLIED_DO { $1 }-| '(/' EXPRESSION_LIST '/)'- { ExpInitialisation () (getTransSpan $1 $3) (fromReverseList $2) }-| operator '(' opCustom ')'- { let TOpCustom _ op = $3- in ExpValue () (getTransSpan $1 $4) (ValOperator op) }-| assignment { ExpValue () (getSpan $1) ValAssignment }-| '*' INTEGER_LITERAL { ExpReturnSpec () (getTransSpan $1 $2) $2 }--DATA_REFS :: { [ Expression A0 ] }-: DATA_REFS ',' DATA_REF { $3 : $1 }-| DATA_REF { [ $1 ] }--DATA_REF :: { Expression A0 }-: DATA_REF '%' PART_REF { ExpDataRef () (getTransSpan $1 $3) $1 $3 }-| PART_REF { $1 }--PART_REFS :: { [ Expression A0 ] }-: PART_REFS ',' PART_REF { $3 : $1 }-| PART_REF { [ $1 ] }--PART_REF :: { Expression A0 }-: VARIABLE { $1 }-| VARIABLE '(' ')'- { ExpFunctionCall () (getTransSpan $1 $3) $1 Nothing }-| VARIABLE '(' INDICIES ')'- { ExpSubscript () (getTransSpan $1 $4) $1 (fromReverseList $3) }-| VARIABLE '(' INDICIES ')' '(' INDICIES ')'- { let innerSub = ExpSubscript () (getTransSpan $1 $4) $1 (fromReverseList $3)- in ExpSubscript () (getTransSpan $1 $7) innerSub (fromReverseList $6) }--INDICIES :: { [ Index A0 ] }-: INDICIES ',' INDEX { $3 : $1 }-| INDEX { [ $1 ] }--INDEX :: { Index A0 }-: RANGE { $1 }-| RANGE ':' EXPRESSION- { let IxRange () s lower upper _ = $1- in IxRange () (getTransSpan s $3) lower upper (Just $3) }-| EXPRESSION { IxSingle () (getSpan $1) Nothing $1 }--- Following is only as an intermediate stage before having been turned into--- an argument by later transformation.-| id '=' EXPRESSION- { let TId s id = $1 in IxSingle () (getTransSpan $1 s) (Just id) $3 }--RANGE :: { Index A0 }-: ':' { IxRange () (getSpan $1) Nothing Nothing Nothing }-| ':' EXPRESSION { IxRange () (getTransSpan $1 $2) Nothing (Just $2) Nothing }-| EXPRESSION ':' { IxRange () (getTransSpan $1 $2) (Just $1) Nothing Nothing }-| EXPRESSION ':' EXPRESSION- { IxRange () (getTransSpan $1 $3) (Just $1) (Just $3) Nothing }--DO_SPECIFICATION :: { DoSpecification A0 }-: EXPRESSION_ASSIGNMENT_STATEMENT ',' EXPRESSION ',' EXPRESSION- { DoSpecification () (getTransSpan $1 $5) $1 $3 (Just $5) }-| EXPRESSION_ASSIGNMENT_STATEMENT ',' EXPRESSION- { DoSpecification () (getTransSpan $1 $3) $1 $3 Nothing }--IMPLIED_DO :: { Expression A0 }-: '(' EXPRESSION ',' DO_SPECIFICATION ')'- { let expList = AList () (getSpan $2) [ $2 ]- in ExpImpliedDo () (getTransSpan $1 $5) expList $4 }-| '(' EXPRESSION ',' EXPRESSION ',' DO_SPECIFICATION ')'- { let expList = AList () (getTransSpan $2 $4) [ $2, $4 ]- in ExpImpliedDo () (getTransSpan $1 $5) expList $6 }-| '(' EXPRESSION ',' EXPRESSION ',' EXPRESSION_LIST ',' DO_SPECIFICATION ')'- { let { exps = reverse $6;- expList = AList () (getTransSpan $2 exps) ($2 : $4 : reverse $6) }- in ExpImpliedDo () (getTransSpan $1 $9) expList $8 }--EXPRESSION_LIST :: { [ Expression A0 ] }-: EXPRESSION_LIST ',' EXPRESSION { $3 : $1 }-| EXPRESSION { [ $1 ] }--ARITHMETIC_SIGN :: { (SrcSpan, UnaryOp) }-: '-' { (getSpan $1, Minus) }-| '+' { (getSpan $1, Plus) }--RELATIONAL_OPERATOR :: { BinaryOp }-: '==' { EQ }-| '!=' { NE }-| '>' { GT }-| '>=' { GTE }-| '<' { LT }-| '<=' { LTE }--VARIABLE :: { Expression A0 }-: id { ExpValue () (getSpan $1) $ let (TId _ s) = $1 in ValVariable s }--NUMERIC_LITERAL :: { Expression A0 }-: INTEGER_LITERAL { $1 } | REAL_LITERAL { $1 }--INTEGERS :: { [ Expression A0 ] }-: INTEGERS ',' INTEGER_LITERAL { $3 : $1 }-| INTEGER_LITERAL { [ $1 ] }--INTEGER_LITERAL :: { Expression A0 }-: int- { let TIntegerLiteral s i = $1- in ExpValue () s $ ValInteger i Nothing }-| int '_' KIND_PARAM- { let TIntegerLiteral s i = $1- in ExpValue () s $ ValInteger i (Just $3) }-| boz { let TBozLiteral s b = $1 in ExpValue () s $ ValBoz b }--REAL_LITERAL :: { Expression A0 }-: float- { let TRealLiteral s r = $1- in ExpValue () s $ ValReal r Nothing }-| float '_' KIND_PARAM- { let TRealLiteral s r = $1- in ExpValue () s $ ValReal r (Just $3) }--LOGICAL_LITERAL :: { Expression A0 }-: bool- { let TLogicalLiteral s b = $1- in ExpValue () s (ValLogical b Nothing) }-| bool '_' KIND_PARAM- { let TLogicalLiteral s b = $1- in ExpValue () s (ValLogical b (Just $3)) }--KIND_PARAM :: { Expression A0 }-: INTEGER_LITERAL { $1 }-| VARIABLE { $1 }--STRING :: { Expression A0 }-: string { let TString s c = $1 in ExpValue () s $ ValString c }--cDATA :: { () } : {% pushContext ConData }-cIMPLICIT :: { () } : {% pushContext ConImplicit }-cNAMELIST :: { () } : {% pushContext ConNamelist }-cCOMMON :: { () } : {% pushContext ConCommon }-cPOP :: { () } : {% popContext }--{--unitNameCheck :: Token -> String -> Parse AlexInput Token ()-unitNameCheck (TId _ name1) name2- | name1 == name2 = return ()- | otherwise = fail "Unit name does not match the corresponding END statement."-unitNameCheck _ _ = return ()--parse = runParse programParser-defTransforms = defaultTransformations Fortran90--fortran90Parser ::- B.ByteString -> String -> ParseResult AlexInput Token (ProgramFile A0)-fortran90Parser = fortran90ParserWithTransforms defTransforms--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--parseError :: Token -> LexAction a-parseError _ = do- parseState <- get-#ifdef DEBUG- tokens <- reverse <$> aiPreviousTokensInLine <$> getAlex-#endif- fail $ psFilename parseState ++ ": parsing failed. "-#ifdef DEBUG- ++ '\n' : show tokens-#endif--}
− src/Language/Fortran/Parser/Fortran95.y
@@ -1,1290 +0,0 @@--- -*- Mode: Haskell -*--{-module Language.Fortran.Parser.Fortran95 ( functionParser- , blockParser- , 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)-import Data.List (nub)-import Data.Either (either, lefts, rights, partitionEithers)-import Control.Applicative-import qualified Data.ByteString.Char8 as B--#ifdef DEBUG-import Data.Data (toConstr)-#endif--import Language.Fortran.Util.Position-import Language.Fortran.Util.ModFile-import Language.Fortran.ParserMonad-import Language.Fortran.Lexer.FreeForm-import Language.Fortran.AST-import Language.Fortran.Transformer--import Debug.Trace--}--%name programParser PROGRAM-%name blockParser BLOCK-%name statementParser STATEMENT-%name functionParser SUBPROGRAM_UNIT-%monad { LexAction }-%lexer { lexer } { TEOF _ }-%tokentype { Token }-%error { parseError }--%token- id { TId _ _ }- comment { TComment _ _ }- string { TString _ _ }- int { TIntegerLiteral _ _ }- float { TRealLiteral _ _ }- boz { TBozLiteral _ _ }- '_' { TUnderscore _ }- ',' { TComma _ }- ',2' { TComma2 _ }- ';' { TSemiColon _ }- ':' { TColon _ }- '::' { TDoubleColon _ }- '=' { TOpAssign _ }- '=>' { TArrow _ }- '%' { TPercent _ }- '(' { TLeftPar _ }- '(2' { TLeftPar2 _ }- ')' { TRightPar _ }- '(/' { TLeftInitPar _ }- '/)' { TRightInitPar _ }- opCustom { TOpCustom _ _ }- '**' { TOpExp _ }- '+' { TOpPlus _ }- '-' { TOpMinus _ }- '*' { TStar _ }- '/' { TOpDivision _ }- slash { TSlash _ }- or { TOpOr _ }- and { TOpAnd _ }- not { TOpNot _ }- eqv { TOpEquivalent _ }- neqv { TOpNotEquivalent _ }- '<' { TOpLT _ }- '<=' { TOpLE _ }- '==' { TOpEQ _ }- '!=' { TOpNE _ }- '>' { TOpGT _ }- '>=' { TOpGE _ }- bool { TLogicalLiteral _ _ }- program { TProgram _ }- endProgram { TEndProgram _ }- function { TFunction _ }- endFunction { TEndFunction _ }- result { TResult _ }- pure { TPure _ }- elemental { TElemental _ }- recursive { TRecursive _ }- subroutine { TSubroutine _ }- endSubroutine { TEndSubroutine _ }- blockData { TBlockData _ }- endBlockData { TEndBlockData _ }- module { TModule _ }- endModule { TEndModule _ }- contains { TContains _ }- use { TUse _ }- only { TOnly _ }- interface { TInterface _ }- endInterface { TEndInterface _ }- moduleProcedure { TModuleProcedure _ }- assignment { TAssignment _ }- operator { TOperator _ }- call { TCall _ }- return { TReturn _ }- entry { TEntry _ }- include { TInclude _ }- public { TPublic _ }- private { TPrivate _ }- parameter { TParameter _ }- allocatable { TAllocatable _ }- dimension { TDimension _ }- external { TExternal _ }- intent { TIntent _ }- intrinsic { TIntrinsic _ }- optional { TOptional _ }- pointer { TPointer _ }- save { TSave _ }- target { TTarget _ }- value { TValue _ }- volatile { TVolatile _ }- in { TIn _ }- out { TOut _ }- inout { TInOut _ }- data { TData _ }- namelist { TNamelist _ }- implicit { TImplicit _ }- equivalence { TEquivalence _ }- common { TCommon _ }- allocate { TAllocate _ }- stat { TStat _ }- deallocate { TDeallocate _ }- nullify { TNullify _ }- none { TNone _ }- goto { TGoto _ }- to { TTo _ }- continue { TContinue _ }- stop { TStop _ }- do { TDo _ }- enddo { TEndDo _ }- while { TWhile _ }- if { TIf _ }- then { TThen _ }- else { TElse _ }- elsif { TElsif _ }- endif { TEndIf _ }- case { TCase _ }- selectcase { TSelectCase _ }- endselect { TEndSelect _ }- default { TDefault _ }- cycle { TCycle _ }- exit { TExit _ }- where { TWhere _ }- elsewhere { TElsewhere _ }- endwhere { TEndWhere _ }- type { TType _ }- endType { TEndType _ }- sequence { TSequence _ }- kind { TKind _ }- len { TLen _ }- integer { TInteger _ }- real { TReal _ }- doublePrecision { TDoublePrecision _ }- logical { TLogical _ }- character { TCharacter _ }- complex { TComplex _ }- open { TOpen _ }- close { TClose _ }- read { TRead _ }- write { TWrite _ }- print { TPrint _ }- backspace { TBackspace _ }- rewind { TRewind _ }- inquire { TInquire _ }- endfile { TEndfile _ }- format { TFormat _ }- blob { TBlob _ _ }- end { TEnd _ }- newline { TNewline _ }- forall { TForall _ }- endforall { TEndForall _ }--- Precedence of operators---- Level 6-%left opCustom---- Level 5-%left eqv neqv-%left or-%left and-%right not---- Level 4-%nonassoc '==' '!=' '>' '<' '>=' '<='-%nonassoc RELATIONAL---- Level 3-%left CONCAT---- Level 2-%left '+' '-'-%left '*' '/'-%right SIGN-%right '**'---- Level 1-%right DEFINED_UNARY---- Level 0-%left '%'--%%--maybe(p)-: p { Just $1 }-| {- empty -} { Nothing }---- This rule is to ignore leading whitespace-PROGRAM :: { ProgramFile A0 }-: NEWLINE PROGRAM_INNER { $2 }-| PROGRAM_INNER { $1 }--PROGRAM_INNER :: { ProgramFile A0 }-: PROGRAM_UNITS { ProgramFile (MetaInfo { miVersion = Fortran95, miFilename = "" }) (reverse $1) }-| {- empty -} { ProgramFile (MetaInfo { miVersion = Fortran95, miFilename = "" }) [] }--PROGRAM_UNITS :: { [ ProgramUnit A0 ] }-: PROGRAM_UNITS PROGRAM_UNIT MAYBE_NEWLINE { $2 : $1 }-| PROGRAM_UNIT MAYBE_NEWLINE { [ $1 ] }--PROGRAM_UNIT :: { ProgramUnit A0 }-: program NAME NEWLINE BLOCKS MAYBE_SUBPROGRAM_UNITS PROGRAM_END- {% do { unitNameCheck $6 $2;- return $ PUMain () (getTransSpan $1 $6) (Just $2) (reverse $4) $5 } }-| module NAME NEWLINE BLOCKS MAYBE_SUBPROGRAM_UNITS MODULE_END- {% do { unitNameCheck $6 $2;- return $ PUModule () (getTransSpan $1 $6) $2 (reverse $4) $5 } }-| blockData NEWLINE BLOCKS BLOCK_DATA_END- { PUBlockData () (getTransSpan $1 $4) Nothing (reverse $3) }-| blockData NAME NEWLINE BLOCKS BLOCK_DATA_END- {% do { unitNameCheck $5 $2;- return $ PUBlockData () (getTransSpan $1 $5) (Just $2) (reverse $4) } }-| SUBPROGRAM_UNIT { $1 }--MAYBE_SUBPROGRAM_UNITS :: { Maybe [ ProgramUnit A0 ] }-: contains NEWLINE SUBPROGRAM_UNITS { Just $ reverse $3 }-| {- Empty -} { Nothing }--SUBPROGRAM_UNITS :: { [ ProgramUnit A0 ] }-: SUBPROGRAM_UNITS SUBPROGRAM_UNIT NEWLINE { $2 : $1 }-| {- EMPTY -} { [ ] }--SUBPROGRAM_UNIT :: { ProgramUnit A0 }-: PREFIXES function NAME MAYBE_ARGUMENTS MAYBE_RESULT MAYBE_COMMENT NEWLINE BLOCKS MAYBE_SUBPROGRAM_UNITS FUNCTION_END- {% do { unitNameCheck $10 $3;- let (pfxs, typeSpec) = case partitionEithers $1 of- { (ps, t:_) -> (fromReverseList' ps, Just t)- ; (ps, []) -> (fromReverseList' ps, Nothing) } in- let sfx = emptySuffixes in- let ss = if null $1 then getTransSpan $2 $10 else getTransSpan (reverse $1) $10 in- if validPrefixSuffix (pfxs, sfx) then- return $ PUFunction () ss typeSpec (pfxs, sfx) $3 $4 $5 (reverse $8) $9- else fail "Cannot specify elemental along with recursive." } }-| PREFIXES subroutine NAME MAYBE_ARGUMENTS MAYBE_COMMENT NEWLINE BLOCKS MAYBE_SUBPROGRAM_UNITS SUBROUTINE_END- {% do { unitNameCheck $9 $3;- (pfxs, typeSpec) <- case partitionEithers $1 of- { (ps, t:_) -> fail "Subroutines cannot have return types."- ; (ps, []) -> return (fromReverseList' ps, Nothing) };- let sfx = emptySuffixes in- let ss = if null $1 then getTransSpan $2 $9 else getTransSpan (reverse $1) $9 in- if validPrefixSuffix (pfxs, sfx) then- return $ PUSubroutine () ss (pfxs, sfx) $3 $4 (reverse $7) $8- else fail "Cannot specify elemental along with recursive." } }-| comment { let (TComment s c) = $1 in PUComment () s (Comment c) }---- (Fortran2003) R1227, Fortran95 (...)-PREFIXES :: { [Either (Prefix A0) (TypeSpec A0)] }-: PREFIXES PREFIX { $2:$1 }-| {- EMPTY -} { [] }---- (Fortran2003) R1228, Fortran95 (...)-PREFIX :: { Either (Prefix A0) (TypeSpec A0) }-: recursive { Left $ PfxRecursive () (getSpan $1) }-| elemental { Left $ PfxElemental () (getSpan $1) }-| pure { Left $ PfxPure () (getSpan $1) }-| TYPE_SPEC { Right $1 }--RESULT :: { Expression A0 }-: result '(' VARIABLE ')' { $3 }--MAYBE_RESULT :: { Maybe (Expression A0) }-: RESULT { Just $1 }-| {- empty -} { Nothing}--MAYBE_ARGUMENTS :: { Maybe (AList Expression A0) }-: '(' MAYBE_VARIABLES ')' { $2 }-| {- Nothing -} { Nothing }--PROGRAM_END :: { Token }-: end { $1 } | endProgram { $1 } | endProgram id { $2 }-MODULE_END :: { Token }-: end { $1 } | endModule { $1 } | endModule id { $2 }-FUNCTION_END :: { Token }-: end { $1 } | endFunction { $1 } | endFunction id { $2 }-SUBROUTINE_END :: { Token }-: end { $1 } | endSubroutine { $1 } | endSubroutine id { $2 }-BLOCK_DATA_END :: { Token }-: end { $1 } | endBlockData { $1 } | endBlockData id { $2 }-INTERFACE_END :: { Token }-: end { $1 } | endInterface { $1 } | endInterface id { $2 }--NAME :: { Name } : id { let (TId _ name) = $1 in name }--BLOCKS :: { [ Block A0 ] } : BLOCKS BLOCK { $2 : $1 } | {- EMPTY -} { [ ] }--BLOCK :: { Block A0 }-: IF_BLOCK MAYBE_COMMENT NEWLINE { $1 }-| CASE_BLOCK MAYBE_COMMENT NEWLINE { $1 }-| INTEGER_LITERAL STATEMENT MAYBE_COMMENT NEWLINE- { BlStatement () (getTransSpan $1 $2) (Just $1) $2 }-| STATEMENT MAYBE_COMMENT NEWLINE { BlStatement () (getSpan $1) Nothing $1 }-| interface MAYBE_EXPRESSION MAYBE_COMMENT NEWLINE SUBPROGRAM_UNITS2 MODULE_PROCEDURES INTERFACE_END MAYBE_COMMENT NEWLINE- { BlInterface () (getTransSpan $1 $9) $2 False (reverse $5) (reverse $6) }-| interface MAYBE_EXPRESSION MAYBE_COMMENT NEWLINE MODULE_PROCEDURES INTERFACE_END MAYBE_COMMENT NEWLINE- { BlInterface () (getTransSpan $1 $8) $2 False [ ] (reverse $5) }-| COMMENT_BLOCK { $1 }--IF_BLOCK :: { Block A0 }-IF_BLOCK-: if '(' EXPRESSION ')' then MAYBE_COMMENT NEWLINE BLOCKS ELSE_BLOCKS- { let { startSpan = getSpan $1;- (endSpan, conds, blocks, endLabel) = $9;- span = getTransSpan startSpan endSpan }- in BlIf () span Nothing Nothing ((Just $3):conds) ((reverse $8):blocks) endLabel }-| id ':' if '(' EXPRESSION ')' then MAYBE_COMMENT NEWLINE BLOCKS ELSE_BLOCKS- { let { TId startSpan startName = $1;- (endSpan, conds, blocks, endLabel) = $11;- span = getTransSpan startSpan endSpan }- in BlIf () span Nothing (Just startName) ((Just $5):conds) ((reverse $10):blocks) endLabel }-| INTEGER_LITERAL if '(' EXPRESSION ')' then MAYBE_COMMENT NEWLINE BLOCKS ELSE_BLOCKS- { let { startSpan = getSpan $1;- startLabel = Just $1;- (endSpan, conds, blocks, endLabel) = $10;- span = getTransSpan startSpan endSpan }- in BlIf () span startLabel Nothing ((Just $4):conds) ((reverse $9):blocks) endLabel }-| INTEGER_LITERAL id ':' if '(' EXPRESSION ')' then MAYBE_COMMENT NEWLINE BLOCKS ELSE_BLOCKS- { let { startSpan = getSpan $1;- startLabel = Just $1;- TId _ startName = $2;- (endSpan, conds, blocks, endLabel) = $12;- span = getTransSpan startSpan endSpan }- in BlIf () span startLabel (Just startName) ((Just $6):conds) ((reverse $11):blocks) endLabel }--ELSE_BLOCKS :: { (SrcSpan, [Maybe (Expression A0)], [[Block A0]], Maybe (Expression A0)) }-ELSE_BLOCKS-: maybe(INTEGER_LITERAL) elsif '(' EXPRESSION ')' then MAYBE_COMMENT NEWLINE BLOCKS ELSE_BLOCKS- { let (endSpan, conds, blocks, endLabel) = $10- in (endSpan, Just $4 : conds, reverse $9 : blocks, endLabel) }-| maybe(INTEGER_LITERAL) else MAYBE_COMMENT NEWLINE BLOCKS END_IF- { let (endSpan, endLabel) = $6- in (endSpan, [Nothing], [reverse $5], endLabel) }-| END_IF { let (endSpan, endLabel) = $1 in (endSpan, [], [], endLabel) }--END_IF :: { (SrcSpan, Maybe (Expression A0)) }-END_IF-: endif { (getSpan $1, Nothing) }-| endif id { (getSpan $2, Nothing) }-| INTEGER_LITERAL endif { (getSpan $2, Just $1) }-| INTEGER_LITERAL endif id { (getSpan $3, Just $1) }--CASE_BLOCK :: { Block A0 }-CASE_BLOCK-: selectcase '(' EXPRESSION ')' MAYBE_COMMENT NEWLINE CASES- { let { (caseRanges, blocks, endLabel, endSpan) = $7;- span = getTransSpan $1 endSpan }- in BlCase () span Nothing Nothing $3 caseRanges blocks endLabel }-| INTEGER_LITERAL selectcase '(' EXPRESSION ')' MAYBE_COMMENT NEWLINE CASES- { let { (caseRanges, blocks, endLabel, endSpan) = $8;- span = getTransSpan $1 endSpan }- in BlCase () span (Just $1) Nothing $4 caseRanges blocks endLabel }-| id ':' selectcase '(' EXPRESSION ')' MAYBE_COMMENT NEWLINE CASES- { let { (caseRanges, blocks, endLabel, endSpan) = $9;- TId s startName = $1;- span = getTransSpan s endSpan }- in BlCase () span Nothing (Just startName) $5 caseRanges blocks endLabel }-| INTEGER_LITERAL id ':' selectcase '(' EXPRESSION ')' MAYBE_COMMENT NEWLINE CASES- { let { (caseRanges, blocks, endLabel, endSpan) = $10;- TId s startName = $2;- span = getTransSpan s endSpan }- in BlCase () span (Just $1) (Just startName) $6 caseRanges blocks endLabel }---- We store line comments as statements, but this raises an issue: we have--- nowhere to place comments after a SELECT CASE but before a CASE. So we drop--- them. The inner CASES_ rule does /not/ use this, because comments can always--- be parsed as belonging to to the above CASE block.-CASES :: { ([Maybe (AList Index A0)], [[Block A0]], Maybe (Expression A0), SrcSpan) }-: COMMENT_BLOCK CASES_ { $2 }-| CASES_ { $1 }--CASES_ :: { ([Maybe (AList Index A0)], [[Block A0]], Maybe (Expression A0), SrcSpan) }-: maybe(INTEGER_LITERAL) case '(' INDICIES ')' MAYBE_COMMENT NEWLINE BLOCKS CASES_- { let (scrutinees, blocks, endLabel, endSpan) = $9- in (Just (fromReverseList $4) : scrutinees, reverse $8 : blocks, endLabel, endSpan) }-| maybe(INTEGER_LITERAL) case default MAYBE_COMMENT NEWLINE BLOCKS END_SELECT- { let (endLabel, endSpan) = $7- in ([Nothing], [$6], endLabel, endSpan) }-| END_SELECT- { let (endLabel, endSpan) = $1- in ([], [], endLabel, endSpan) }--END_SELECT :: { (Maybe (Expression A0), SrcSpan) }-: maybe(INTEGER_LITERAL) endselect maybe(id)- { ($1, maybe (getSpan $2) getSpan $3) }--MAYBE_EXPRESSION :: { Maybe (Expression A0) }-: EXPRESSION { Just $1 }-| {- EMPTY -} { Nothing }--MAYBE_COMMENT :: { Maybe Token }-: comment { Just $1 }-| {- EMPTY -} { Nothing }--SUBPROGRAM_UNITS2 :: { [ ProgramUnit A0 ] }-: SUBPROGRAM_UNITS SUBPROGRAM_UNIT NEWLINE { $2 : $1 }--MODULE_PROCEDURES :: { [ Block A0 ] }-: MODULE_PROCEDURES MODULE_PROCEDURE { $2 : $1 }-| MODULE_PROCEDURES MODULE_PROCEDURE COMMENT_BLOCK { $3 : $2 : $1 }-| { [ ] }--MODULE_PROCEDURE :: { Block A0 }-: moduleProcedure VARIABLES MAYBE_COMMENT NEWLINE- { let { al = fromReverseList $2;- st = StModuleProcedure () (getTransSpan $1 al) (fromReverseList $2) }- in BlStatement () (getTransSpan $1 $4) Nothing st }--COMMENT_BLOCK :: { Block A0 }-: comment NEWLINE { let (TComment s c) = $1 in BlComment () s (Comment c) }--MAYBE_NEWLINE :: { Maybe Token } : NEWLINE { Just $1 } | {- EMPTY -} { Nothing }--NEWLINE :: { Token }-: NEWLINE newline { $1 }-| NEWLINE ';' { $1 }-| newline { $1 }-| ';' { $1 }--STATEMENT :: { Statement A0 }-: NONEXECUTABLE_STATEMENT { $1 }-| EXECUTABLE_STATEMENT { $1 }--EXPRESSION_ASSIGNMENT_STATEMENT :: { Statement A0 }-: DATA_REF '=' EXPRESSION { StExpressionAssign () (getTransSpan $1 $3) $1 $3 }--NONEXECUTABLE_STATEMENT :: { Statement A0 }-: DECLARATION_STATEMENT { $1 }-| intent '(' INTENT_CHOICE ')' MAYBE_DCOLON EXPRESSION_LIST- { let expAList = fromReverseList $6- in StIntent () (getTransSpan $1 expAList) $3 expAList }-| optional MAYBE_DCOLON EXPRESSION_LIST- { let expAList = fromReverseList $3- in StOptional () (getTransSpan $1 expAList) expAList }-| public MAYBE_DCOLON EXPRESSION_LIST- { let expAList = fromReverseList $3- in StPublic () (getTransSpan $1 expAList) (Just expAList) }-| public { StPublic () (getSpan $1) Nothing }-| private MAYBE_DCOLON EXPRESSION_LIST- { let expAList = fromReverseList $3- in StPrivate () (getTransSpan $1 expAList) (Just expAList) }-| private { StPrivate () (getSpan $1) Nothing }-| save MAYBE_DCOLON SAVE_ARGS- { let saveAList = (fromReverseList $3)- in StSave () (getTransSpan $1 saveAList) (Just saveAList) }-| save { StSave () (getSpan $1) Nothing }-| dimension MAYBE_DCOLON INITIALIZED_DECLARATOR_LIST- { let declAList = fromReverseList $3- in StDimension () (getTransSpan $1 declAList) declAList }-| allocatable MAYBE_DCOLON INITIALIZED_DECLARATOR_LIST- { let declAList = fromReverseList $3- in StAllocatable () (getTransSpan $1 declAList) declAList }-| pointer MAYBE_DCOLON INITIALIZED_DECLARATOR_LIST- { let declAList = fromReverseList $3- in StPointer () (getTransSpan $1 declAList) declAList }-| target MAYBE_DCOLON INITIALIZED_DECLARATOR_LIST- { let declAList = fromReverseList $3- in StTarget () (getTransSpan $1 declAList) declAList }-| value MAYBE_DCOLON INITIALIZED_DECLARATOR_LIST- { let declAList = fromReverseList $3- in StValue () (getTransSpan $1 declAList) declAList }-| volatile MAYBE_DCOLON INITIALIZED_DECLARATOR_LIST- { let declAList = fromReverseList $3- in StVolatile () (getTransSpan $1 declAList) declAList }-| data cDATA DATA_GROUPS cPOP- { let dataAList = fromReverseList $3- in StData () (getTransSpan $1 dataAList) dataAList }-| parameter '(' PARAMETER_ASSIGNMENTS ')'- { let declAList = fromReverseList $3- in StParameter () (getTransSpan $1 $4) declAList }-| implicit none { StImplicit () (getTransSpan $1 $2) Nothing }-| implicit cIMPLICIT IMP_LISTS cPOP- { let impAList = fromReverseList $3- in StImplicit () (getTransSpan $1 impAList) $ Just $ impAList }-| namelist cNAMELIST NAMELISTS cPOP- { let nameALists = fromReverseList $3- in StNamelist () (getTransSpan $1 nameALists) nameALists }-| equivalence EQUIVALENCE_GROUPS- { let eqALists = fromReverseList $2- in StEquivalence () (getTransSpan $1 eqALists) eqALists }-| common cCOMMON COMMON_GROUPS cPOP- { let commonAList = fromReverseList $3- in StCommon () (getTransSpan $1 commonAList) commonAList }-| external MAYBE_DCOLON VARIABLES- { let alist = fromReverseList $3- in StExternal () (getTransSpan $1 alist) alist }-| intrinsic MAYBE_DCOLON VARIABLES- { let alist = fromReverseList $3- in StIntrinsic () (getTransSpan $1 alist) alist }-| use VARIABLE { StUse () (getTransSpan $1 $2) $2 Nothing Permissive Nothing }-| use VARIABLE ',' RENAME_LIST- { let alist = fromReverseList $4- in StUse () (getTransSpan $1 alist) $2 Nothing Permissive (Just alist) }-| use VARIABLE ',' only ':' MAYBE_RENAME_LIST- { StUse () (getTransSpan $1 ($5, $6)) $2 Nothing Exclusive $6 }-| entry VARIABLE MAYBE_RESULT- { StEntry () (getTransSpan $1 $ maybe (getSpan $2) getSpan $3) $2 Nothing $3 }-| entry VARIABLE '(' ')' MAYBE_RESULT- { StEntry () (getTransSpan $1 $ maybe (getSpan $4) getSpan $5) $2 Nothing $5 }-| entry VARIABLE '(' VARIABLES ')' MAYBE_RESULT- { StEntry () (getTransSpan $1 $ maybe (getSpan $5) getSpan $6) $2 (Just $ fromReverseList $4) $6 }-| sequence { StSequence () (getSpan $1) }-| type ATTRIBUTE_LIST '::' id- { let { TId span id = $4;- alist = if null $2 then Nothing else (Just . fromReverseList) $2 }- in StType () (getTransSpan $1 span) alist id }-| type id- { let TId span id = $2 in StType () (getTransSpan $1 span) Nothing id }-| endType { StEndType () (getSpan $1) Nothing }-| endType id- { let TId span id = $2 in StEndType () (getTransSpan $1 span) (Just id) }-| include STRING { StInclude () (getTransSpan $1 $2) $2 Nothing }--- Following is a fake node to make arbitrary FORMAT statements parsable.--- Must be fixed in the future. TODO-| format blob- { let TBlob s blob = $2 in StFormatBogus () (getTransSpan $1 s) blob }--EXECUTABLE_STATEMENT :: { Statement A0 }-: allocate '(' DATA_REFS MAYBE_ALLOC_OPT_LIST ')'- { StAllocate () (getTransSpan $1 $5) Nothing (fromReverseList $3) $4 }-| nullify '(' DATA_REFS ')'- { StNullify () (getTransSpan $1 $4) (fromReverseList $3) }-| deallocate '(' DATA_REFS MAYBE_ALLOC_OPT_LIST ')'- { StDeallocate () (getTransSpan $1 $5) (fromReverseList $3) $4 }-| EXPRESSION_ASSIGNMENT_STATEMENT { $1 }-| POINTER_ASSIGNMENT_STMT { $1 }-| where '(' EXPRESSION ')' EXPRESSION_ASSIGNMENT_STATEMENT- { StWhere () (getTransSpan $1 $5) $3 $5 }-| where '(' EXPRESSION ')' { StWhereConstruct () (getTransSpan $1 $4) Nothing $3 }-| elsewhere '(' EXPRESSION ')' { StElsewhere () (getTransSpan $1 $4) Nothing (Just $3) }-| elsewhere { StElsewhere () (getSpan $1) Nothing Nothing }-| endwhere { StEndWhere () (getSpan $1) Nothing }-| if '(' EXPRESSION ')' INTEGER_LITERAL ',' INTEGER_LITERAL ',' INTEGER_LITERAL- { StIfArithmetic () (getTransSpan $1 $9) $3 $5 $7 $9 }-| do { StDo () (getSpan $1) Nothing Nothing Nothing }-| id ':' do- { let TId s id = $1- in StDo () (getTransSpan s $3) (Just id) Nothing Nothing }-| do INTEGER_LITERAL MAYBE_COMMA DO_SPECIFICATION- { StDo () (getTransSpan $1 $4) Nothing (Just $2) (Just $4) }-| do DO_SPECIFICATION { StDo () (getTransSpan $1 $2) Nothing Nothing (Just $2) }-| id ':' do DO_SPECIFICATION- { let TId s id = $1- in StDo () (getTransSpan s $4) (Just id) Nothing (Just $4) }-| do INTEGER_LITERAL MAYBE_COMMA while '(' EXPRESSION ')'- { StDoWhile () (getTransSpan $1 $7) Nothing (Just $2) $6 }-| do while '(' EXPRESSION ')'- { StDoWhile () (getTransSpan $1 $5) Nothing Nothing $4 }-| id ':' do while '(' EXPRESSION ')'- { let TId s id = $1- in StDoWhile () (getTransSpan s $7) (Just id) Nothing $6 }-| enddo { StEnddo () (getSpan $1) Nothing }-| enddo id- { let TId s id = $2 in StEnddo () (getTransSpan $1 s) (Just id) }-| cycle { StCycle () (getSpan $1) Nothing }-| cycle VARIABLE { StCycle () (getTransSpan $1 $2) (Just $2) }-| exit { StExit () (getSpan $1) Nothing }-| exit VARIABLE { StExit () (getTransSpan $1 $2) (Just $2) }--- GO TO label-| goto INTEGER_LITERAL { StGotoUnconditional () (getTransSpan $1 $2) $2 }--- GO TO label-list [,] scalar-int-expression-| goto '(' INTEGERS ')' MAYBE_COMMA EXPRESSION- { StGotoComputed () (getTransSpan $1 $6) (fromReverseList $3) $6 }-| continue { StContinue () (getSpan $1) }-| stop { StStop () (getSpan $1) Nothing }-| stop EXPRESSION { StStop () (getTransSpan $1 $2) (Just $2) }-| if '(' EXPRESSION ')' EXECUTABLE_STATEMENT- { StIfLogical () (getTransSpan $1 $5) $3 $5 }-| read CILIST IN_IOLIST- { let alist = fromReverseList $3- in StRead () (getTransSpan $1 alist) $2 (Just alist) }-| read CILIST { StRead () (getTransSpan $1 $2) $2 Nothing }-| read FORMAT_ID ',' IN_IOLIST- { let alist = fromReverseList $4- in StRead2 () (getTransSpan $1 alist) $2 (Just alist) }-| read FORMAT_ID { StRead2 () (getTransSpan $1 $2) $2 Nothing }-| write CILIST OUT_IOLIST- { let alist = fromReverseList $3- in StWrite () (getTransSpan $1 alist) $2 (Just alist) }-| write CILIST { StWrite () (getTransSpan $1 $2) $2 Nothing }-| print FORMAT_ID ',' OUT_IOLIST- { let alist = fromReverseList $4- in StPrint () (getTransSpan $1 alist) $2 (Just alist) }-| print FORMAT_ID { StPrint () (getTransSpan $1 $2) $2 Nothing }-| open CILIST { StOpen () (getTransSpan $1 $2) $2 }-| close CILIST { StClose () (getTransSpan $1 $2) $2 }-| inquire CILIST { StInquire () (getTransSpan $1 $2) $2 }-| rewind CILIST { StRewind () (getTransSpan $1 $2) $2 }-| rewind UNIT { StRewind2 () (getTransSpan $1 $2) $2 }-| endfile CILIST { StEndfile () (getTransSpan $1 $2) $2 }-| endfile UNIT { StEndfile2 () (getTransSpan $1 $2) $2 }-| backspace CILIST { StBackspace () (getTransSpan $1 $2) $2 }-| backspace UNIT { StBackspace2 () (getTransSpan $1 $2) $2 }-| call VARIABLE { StCall () (getTransSpan $1 $2) $2 Nothing }-| call VARIABLE '(' ')' { StCall () (getTransSpan $1 $4) $2 Nothing }-| call VARIABLE '(' ARGUMENTS ')'- { let alist = fromReverseList $4- in StCall () (getTransSpan $1 $5) $2 (Just alist) }-| return { StReturn () (getSpan $1) Nothing }-| return EXPRESSION { StReturn () (getTransSpan $1 $2) (Just $2) }-| FORALL { $1 }-| END_FORALL { $1 }--ARGUMENTS :: { [ Argument A0 ] }-: ARGUMENTS ',' ARGUMENT { $3 : $1 }-| ARGUMENT { [ $1 ] }--ARGUMENT :: { Argument A0 }-: id '=' EXPRESSION- { let TId span keyword = $1- in Argument () (getTransSpan span $3) (Just keyword) $3 }-| EXPRESSION- { Argument () (getSpan $1) Nothing $1 }--MAYBE_RENAME_LIST :: { Maybe (AList Use A0) }-: RENAME_LIST { Just $ fromReverseList $1 }-| {- empty -} { Nothing }--RENAME_LIST :: { [ Use A0 ] }-: RENAME_LIST ',' RENAME { $3 : $1 }-| RENAME { [ $1 ] }--RENAME :: { Use A0 }-: VARIABLE '=>' VARIABLE { UseRename () (getTransSpan $1 $3) $1 $3 }-| VARIABLE { UseID () (getSpan $1) $1 }-| operator '(' opCustom ')'- { let TOpCustom ss op = $3- in UseID () (getTransSpan $1 $4) (ExpValue () ss (ValOperator op)) }-| assignment { UseID () (getSpan $1) (ExpValue () (getSpan $1) ValAssignment) }--MAYBE_DCOLON :: { () } : '::' { () } | {- EMPTY -} { () }--FORMAT_ID :: { Expression A0 }-: FORMAT_ID '/' '/' FORMAT_ID %prec CONCAT- { ExpBinary () (getTransSpan $1 $4) Concatenation $1 $4 }-| INTEGER_LITERAL { $1 }-| STRING { $1 }-| DATA_REF { $1 }-| '*' { ExpValue () (getSpan $1) ValStar }--UNIT :: { Expression A0 }-: INTEGER_LITERAL { $1 }-| DATA_REF { $1 }-| '*' { ExpValue () (getSpan $1) ValStar }--CILIST :: { AList ControlPair A0 }-: '(' CILIST_ELEMENT ',' FORMAT_ID ',' CILIST_PAIRS ')'- { let { cp1 = ControlPair () (getSpan $2) Nothing $2;- cp2 = ControlPair () (getSpan $4) Nothing $4;- tail = fromReverseList $6 }- in setSpan (getTransSpan $1 $7) $ cp1 `aCons` cp2 `aCons` tail }-| '(' CILIST_ELEMENT ',' FORMAT_ID ')'- { let { cp1 = ControlPair () (getSpan $2) Nothing $2;- cp2 = ControlPair () (getSpan $4) Nothing $4 }- in AList () (getTransSpan $1 $5) [ cp1, cp2 ] }-| '(' CILIST_ELEMENT ',' CILIST_PAIRS ')'- { let { cp1 = ControlPair () (getSpan $2) Nothing $2;- tail = fromReverseList $4 }- in setSpan (getTransSpan $1 $5) $ cp1 `aCons` tail }-| '(' CILIST_ELEMENT ')'- { let cp1 = ControlPair () (getSpan $2) Nothing $2- in AList () (getTransSpan $1 $3) [ cp1 ] }-| '(' CILIST_PAIRS ')' { fromReverseList $2 }--CILIST_PAIRS :: { [ ControlPair A0 ] }-: CILIST_PAIRS ',' CILIST_PAIR { $3 : $1 }-| CILIST_PAIR { [ $1 ] }--CILIST_PAIR :: { ControlPair A0 }-: id '=' CILIST_ELEMENT- { let (TId s id) = $1 in ControlPair () (getTransSpan s $3) (Just id) $3 }--CILIST_ELEMENT :: { Expression A0 }-: CI_EXPRESSION { $1 }-| '*' { ExpValue () (getSpan $1) ValStar }--CI_EXPRESSION :: { Expression A0 }-: CI_EXPRESSION '+' CI_EXPRESSION- { ExpBinary () (getTransSpan $1 $3) Addition $1 $3 }-| CI_EXPRESSION '-' CI_EXPRESSION- { ExpBinary () (getTransSpan $1 $3) Subtraction $1 $3 }-| CI_EXPRESSION '*' CI_EXPRESSION- { ExpBinary () (getTransSpan $1 $3) Multiplication $1 $3 }-| CI_EXPRESSION '/' CI_EXPRESSION- { ExpBinary () (getTransSpan $1 $3) Division $1 $3 }-| CI_EXPRESSION '**' CI_EXPRESSION- { ExpBinary () (getTransSpan $1 $3) Exponentiation $1 $3 }-| CI_EXPRESSION '/' '/' CI_EXPRESSION %prec CONCAT- { ExpBinary () (getTransSpan $1 $4) Concatenation $1 $4 }-| ARITHMETIC_SIGN CI_EXPRESSION %prec SIGN- { ExpUnary () (getTransSpan (fst $1) $2) (snd $1) $2 }-| CI_EXPRESSION or CI_EXPRESSION- { ExpBinary () (getTransSpan $1 $3) Or $1 $3 }-| CI_EXPRESSION and CI_EXPRESSION- { ExpBinary () (getTransSpan $1 $3) And $1 $3 }-| not CI_EXPRESSION- { ExpUnary () (getTransSpan $1 $2) Not $2 }-| CI_EXPRESSION eqv CI_EXPRESSION- { ExpBinary () (getTransSpan $1 $3) Equivalent $1 $3 }-| CI_EXPRESSION neqv CI_EXPRESSION- { ExpBinary () (getTransSpan $1 $3) NotEquivalent $1 $3 }-| CI_EXPRESSION RELATIONAL_OPERATOR CI_EXPRESSION %prec RELATIONAL- { ExpBinary () (getTransSpan $1 $3) $2 $1 $3 }-| opCustom CI_EXPRESSION %prec DEFINED_UNARY- { let TOpCustom span str = $1- in ExpUnary () (getTransSpan span $2) (UnCustom str) $2 }-| CI_EXPRESSION opCustom CI_EXPRESSION- { let TOpCustom _ str = $2- in ExpBinary () (getTransSpan $1 $3) (BinCustom str) $1 $3 }-| '(' CI_EXPRESSION ')' { setSpan (getTransSpan $1 $3) $2 }-| INTEGER_LITERAL { $1 }-| LOGICAL_LITERAL { $1 }-| STRING { $1 }-| DATA_REF { $1 }--{- p67 ALLOCATE statement -}-MAYBE_ALLOC_OPT_LIST :: { Maybe (AList AllocOpt A0) }-: ',' stat '=' EXPRESSION { Just (fromReverseList [AOStat () (getTransSpan $2 $4) $4]) }-| {- empty -} { Nothing }--IN_IOLIST :: { [ Expression A0 ] }-: IN_IOLIST ',' IN_IO_ELEMENT { $3 : $1}-| IN_IO_ELEMENT { [ $1 ] }--IN_IO_ELEMENT :: { Expression A0 }-: DATA_REF { $1 }-| '(' IN_IOLIST ',' DO_SPECIFICATION ')'- { ExpImpliedDo () (getTransSpan $1 $5) (fromReverseList $2) $4 }--OUT_IOLIST :: { [ Expression A0 ] }-: OUT_IOLIST ',' EXPRESSION { $3 : $1}-| EXPRESSION { [ $1 ] }--COMMON_GROUPS :: { [ CommonGroup A0 ] }-: COMMON_GROUPS COMMON_GROUP { $2 : $1 }-| COMMON_GROUPS ',2' COMMON_GROUP { $3 : $1 }-| INIT_COMMON_GROUP { [ $1 ] }--COMMON_GROUP :: { CommonGroup A0 }-: COMMON_NAME UNINITIALIZED_DECLARATOR_LIST- { let alist = fromReverseList $2- in CommonGroup () (getTransSpan $1 alist) (Just $1) alist }-| '/' '/' UNINITIALIZED_DECLARATOR_LIST- { let alist = fromReverseList $3- in CommonGroup () (getTransSpan $1 alist) Nothing alist }--INIT_COMMON_GROUP :: { CommonGroup A0 }-: COMMON_NAME UNINITIALIZED_DECLARATOR_LIST- { let alist = fromReverseList $2- in CommonGroup () (getTransSpan $1 alist) (Just $1) alist }-| '/' '/' UNINITIALIZED_DECLARATOR_LIST- { let alist = fromReverseList $3- in CommonGroup () (getTransSpan $1 alist) Nothing alist }-| UNINITIALIZED_DECLARATOR_LIST- { let alist = fromReverseList $1- in CommonGroup () (getSpan alist) Nothing alist }--EQUIVALENCE_GROUPS :: { [ AList Expression A0 ] }-: EQUIVALENCE_GROUPS ',' '(' PART_REFS ')'- { setSpan (getTransSpan $3 $5) (fromReverseList $4) : $1 }-| '(' PART_REFS ')'- { [ setSpan (getTransSpan $1 $3) (fromReverseList $2) ] }--NAMELISTS :: { [ Namelist A0 ] }-: NAMELISTS NAMELIST { $2 : $1 }-| NAMELISTS ',2' NAMELIST { $3 : $1 }-| NAMELIST { [ $1 ] }--NAMELIST :: { Namelist A0 }-: '/' VARIABLE '/' VARIABLES- { Namelist () (getTransSpan $1 $4) $2 $ fromReverseList $4 }--MAYBE_VARIABLES :: { Maybe (AList Expression A0) }-: VARIABLES { Just $ fromReverseList $1 } | {- EMPTY -} { Nothing }--VARIABLES :: { [ Expression A0 ] }-: VARIABLES ',' VARIABLE { $3 : $1 }-| VARIABLE { [ $1 ] }--IMP_LISTS :: { [ ImpList A0 ] }-: IMP_LISTS ',' IMP_LIST { $3 : $1 }-| IMP_LIST { [ $1 ] }--IMP_LIST :: { ImpList A0 }-: TYPE_SPEC '(2' IMP_ELEMENTS ')'- { ImpList () (getTransSpan $1 $4) $1 (aReverse $3) }--IMP_ELEMENTS :: { AList ImpElement A0 }-: IMP_ELEMENTS ',' IMP_ELEMENT { setSpan (getTransSpan $1 $3) $ $3 `aCons` $1 }-| IMP_ELEMENT { AList () (getSpan $1) [ $1 ] }--IMP_ELEMENT :: { ImpElement A0 }-: id {% do- let (TId s id) = $1- if length id /= 1- then fail "Implicit argument must be a character."- else return $ ImpCharacter () s id- }-| id '-' id {% do- let (TId _ id1) = $1- let (TId _ id2) = $3- if length id1 /= 1 || length id2 /= 1- then fail "Implicit argument must be a character."- else return $ ImpRange () (getTransSpan $1 $3) id1 id2- }--PARAMETER_ASSIGNMENTS :: { [ Declarator A0 ] }-: PARAMETER_ASSIGNMENTS ',' PARAMETER_ASSIGNMENT { $3 : $1 }-| PARAMETER_ASSIGNMENT { [ $1 ] }--PARAMETER_ASSIGNMENT :: { Declarator A0 }-: VARIABLE '=' EXPRESSION- { Declarator () (getTransSpan $1 $3) $1 ScalarDecl Nothing (Just $3) }--DECLARATION_STATEMENT :: { Statement A0 }-: TYPE_SPEC ATTRIBUTE_LIST '::' INITIALIZED_DECLARATOR_LIST- { let { mAttrAList = if null $2 then Nothing else Just $ fromReverseList $2;- declAList = fromReverseList $4 }- in StDeclaration () (getTransSpan $1 declAList) $1 mAttrAList declAList }-| TYPE_SPEC INITIALIZED_DECLARATOR_LIST- { let { declAList = fromReverseList $2 }- in StDeclaration () (getTransSpan $1 declAList) $1 Nothing declAList }--ATTRIBUTE_LIST :: { [ Attribute A0 ] }-: ATTRIBUTE_LIST ',' ATTRIBUTE_SPEC { $3 : $1 }-| {- EMPTY -} { [ ] }--ATTRIBUTE_SPEC :: { Attribute A0 }-: public { AttrPublic () (getSpan $1) }-| private { AttrPrivate () (getSpan $1) }-| allocatable { AttrAllocatable () (getSpan $1) }-| dimension '(' DIMENSION_DECLARATORS ')'- { AttrDimension () (getTransSpan $1 $4) (aReverse $3) }-| external { AttrExternal () (getSpan $1) }-| intent '(' INTENT_CHOICE ')' { AttrIntent () (getTransSpan $1 $4) $3 }-| intrinsic { AttrIntrinsic () (getSpan $1) }-| optional { AttrOptional () (getSpan $1) }-| pointer { AttrPointer () (getSpan $1) }-| parameter { AttrParameter () (getSpan $1) }-| save { AttrSave () (getSpan $1) }-| target { AttrTarget () (getSpan $1) }-| value { AttrValue () (getSpan $1) }-| volatile { AttrVolatile () (getSpan $1) }--INTENT_CHOICE :: { Intent } : in { In } | out { Out } | inout { InOut }--DATA_GROUPS :: { [ DataGroup A0 ] }-: DATA_GROUPS MAYBE_COMMA DATA_LIST slash EXPRESSION_LIST slash- { let { nameAList = fromReverseList $3;- dataAList = fromReverseList $5 }- in DataGroup () (getTransSpan nameAList $6) nameAList dataAList : $1 }-| DATA_LIST slash EXPRESSION_LIST slash- { let { nameAList = fromReverseList $1;- dataAList = fromReverseList $3 }- in [ DataGroup () (getTransSpan nameAList $4) nameAList dataAList ] }--MAYBE_COMMA :: { () } : ',' { () } | {- EMPTY -} { () }--DATA_LIST :: { [ Expression A0 ] }-: DATA_LIST ',' DATA_ELEMENT { $3 : $1 }-| DATA_ELEMENT { [ $1 ] }--DATA_ELEMENT :: { Expression A0 }-: DATA_REF { $1 } | IMPLIED_DO { $1 }--SAVE_ARGS :: { [ Expression A0 ] }-: SAVE_ARGS ',' SAVE_ARG { $3 : $1 } | SAVE_ARG { [ $1 ] }--SAVE_ARG :: { Expression A0 } : COMMON_NAME { $1 } | VARIABLE { $1 }--COMMON_NAME :: { Expression A0 }-: '/' VARIABLE '/' { setSpan (getTransSpan $1 $3) $2 }--INITIALIZED_DECLARATOR_LIST :: { [ Declarator A0 ] }-: INITIALIZED_DECLARATOR_LIST ',' INITIALIZED_DECLARATOR { $3 : $1 }-| INITIALIZED_DECLARATOR { [ $1 ] }--UNINITIALIZED_DECLARATOR_LIST :: { [ Declarator A0 ] }-: UNINITIALIZED_DECLARATOR_LIST ',' DECLARATOR { $3 : $1 }-| DECLARATOR { [ $1 ] }--INITIALIZED_DECLARATOR :: { Declarator A0 }-: DECLARATOR '=' EXPRESSION { setInitialisation $1 $3 }-| DECLARATOR '=>' EXPRESSION { setInitialisation $1 $3 }-| DECLARATOR { $1 }--DECLARATOR :: { Declarator A0 }-: VARIABLE- { Declarator () (getSpan $1) $1 ScalarDecl Nothing Nothing }-| VARIABLE '*' EXPRESSION- { Declarator () (getTransSpan $1 $3) $1 ScalarDecl (Just $3) Nothing }-| VARIABLE '*' '(' '*' ')'- { let star = ExpValue () (getSpan $4) ValStar- in Declarator () (getTransSpan $1 $5) $1 ScalarDecl (Just star) Nothing }-| VARIABLE '(' DIMENSION_DECLARATORS ')'- { Declarator () (getTransSpan $1 $4) $1 (ArrayDecl (aReverse $3)) Nothing Nothing }-| VARIABLE '(' DIMENSION_DECLARATORS ')' '*' EXPRESSION- { Declarator () (getTransSpan $1 $6) $1 (ArrayDecl (aReverse $3)) (Just $6) Nothing }--- nonstandard char array syntax (wrong order for dimensions & charlen)-| VARIABLE '*' EXPRESSION '(' DIMENSION_DECLARATORS ')'- { Declarator () (getTransSpan $1 $6) $1 (ArrayDecl (aReverse $5)) (Just $3) Nothing }-| VARIABLE '(' DIMENSION_DECLARATORS ')' '*' '(' '*' ')'- { let star = ExpValue () (getSpan $7) ValStar- in Declarator () (getTransSpan $1 $8) $1 (ArrayDecl (aReverse $3)) (Just star) Nothing }--DIMENSION_DECLARATORS :: { AList DimensionDeclarator A0 }-: DIMENSION_DECLARATORS ',' DIMENSION_DECLARATOR- { setSpan (getTransSpan $1 $3) $ $3 `aCons` $1 }-| DIMENSION_DECLARATOR- { AList () (getSpan $1) [ $1 ] }--DIMENSION_DECLARATOR :: { DimensionDeclarator A0 }-: EXPRESSION ':' EXPRESSION- { DimensionDeclarator () (getTransSpan $1 $3) (Just $1) (Just $3) }-| EXPRESSION { DimensionDeclarator () (getSpan $1) Nothing (Just $1) }--- Lower bound only-| EXPRESSION ':'- { DimensionDeclarator () (getTransSpan $1 $2) (Just $1) Nothing }-| EXPRESSION ':' '*'- { let { span = getSpan $3;- star = ExpValue () span ValStar }- in DimensionDeclarator () (getTransSpan $1 span) (Just $1) (Just star) }-| '*'- { let { span = getSpan $1;- star = ExpValue () span ValStar }- in DimensionDeclarator () span Nothing (Just star) }-| ':'- { let span = getSpan $1- in DimensionDeclarator () span Nothing Nothing }--TYPE_SPEC :: { TypeSpec A0 }-: integer KIND_SELECTOR { TypeSpec () (getSpan ($1, $2)) TypeInteger $2 }-| real KIND_SELECTOR { TypeSpec () (getSpan ($1, $2)) TypeReal $2 }-| doublePrecision { TypeSpec () (getSpan $1) TypeDoublePrecision Nothing }-| complex KIND_SELECTOR { TypeSpec () (getSpan ($1, $2)) TypeComplex $2 }-| character CHAR_SELECTOR { TypeSpec () (getSpan ($1, $2)) TypeCharacter $2 }-| logical KIND_SELECTOR { TypeSpec () (getSpan ($1, $2)) TypeLogical $2 }-| type '(' id ')'- { let TId _ id = $3- in TypeSpec () (getTransSpan $1 $4) (TypeCustom id) Nothing }--KIND_SELECTOR :: { Maybe (Selector A0) }-: '(' EXPRESSION ')'- { Just $ Selector () (getTransSpan $1 $3) Nothing (Just $2) }-| '(' kind '=' EXPRESSION ')'- { Just $ Selector () (getTransSpan $1 $5) Nothing (Just $4) }-| '*' EXPRESSION -- non-standard but commonly used extension- { Just $ Selector () (getTransSpan $1 $2) Nothing (Just $2) }-| {- EMPTY -} { Nothing }--CHAR_SELECTOR :: { Maybe (Selector A0) }-: '*' EXPRESSION- { Just $ Selector () (getTransSpan $1 $2) (Just $2) Nothing }--- The following rule is a bug in the spec.--- | '*' EXPRESSION ','--- { Just $ Selector () (getTransSpan $1 $2) (Just $2) Nothing }-| '*' '(' '*' ')'- { let star = ExpValue () (getSpan $3) ValStar- in Just $ Selector () (getTransSpan $1 $4) (Just star) Nothing }-| '(' LEN_EXPRESSION ')'- { Just $ Selector () (getTransSpan $1 $3) (Just $2) Nothing }-| '(' len '=' LEN_EXPRESSION ')'- { Just $ Selector () (getTransSpan $1 $5) (Just $4) Nothing }-| '(' kind '=' EXPRESSION ')'- { Just $ Selector () (getTransSpan $1 $5) Nothing (Just $4) }-| '(' LEN_EXPRESSION ',' EXPRESSION ')'- { Just $ Selector () (getTransSpan $1 $5) (Just $2) (Just $4) }-| '(' LEN_EXPRESSION ',' kind '=' EXPRESSION ')'- { Just $ Selector () (getTransSpan $1 $7) (Just $2) (Just $6) }-| '(' len '=' LEN_EXPRESSION ',' kind '=' EXPRESSION ')'- { Just $ Selector () (getTransSpan $1 $9) (Just $4) (Just $8) }-| '(' kind '=' EXPRESSION ',' len '=' LEN_EXPRESSION ')'- { Just $ Selector () (getTransSpan $1 $9) (Just $8) (Just $4) }-| {- EMPTY -} { Nothing }--LEN_EXPRESSION :: { Expression A0 }-: EXPRESSION { $1 }-| '*' { ExpValue () (getSpan $1) ValStar }--EXPRESSION :: { Expression A0 }-: EXPRESSION '+' EXPRESSION- { ExpBinary () (getTransSpan $1 $3) Addition $1 $3 }-| EXPRESSION '-' EXPRESSION- { ExpBinary () (getTransSpan $1 $3) Subtraction $1 $3 }-| EXPRESSION '*' EXPRESSION- { ExpBinary () (getTransSpan $1 $3) Multiplication $1 $3 }-| EXPRESSION '/' EXPRESSION- { ExpBinary () (getTransSpan $1 $3) Division $1 $3 }-| EXPRESSION '**' EXPRESSION- { ExpBinary () (getTransSpan $1 $3) Exponentiation $1 $3 }-| EXPRESSION '/' '/' EXPRESSION %prec CONCAT- { ExpBinary () (getTransSpan $1 $4) Concatenation $1 $4 }-| ARITHMETIC_SIGN EXPRESSION %prec SIGN- { ExpUnary () (getTransSpan (fst $1) $2) (snd $1) $2 }-| EXPRESSION or EXPRESSION- { ExpBinary () (getTransSpan $1 $3) Or $1 $3 }-| EXPRESSION and EXPRESSION- { ExpBinary () (getTransSpan $1 $3) And $1 $3 }-| not EXPRESSION- { ExpUnary () (getTransSpan $1 $2) Not $2 }-| EXPRESSION eqv EXPRESSION- { ExpBinary () (getTransSpan $1 $3) Equivalent $1 $3 }-| EXPRESSION neqv EXPRESSION- { ExpBinary () (getTransSpan $1 $3) NotEquivalent $1 $3 }-| EXPRESSION RELATIONAL_OPERATOR EXPRESSION %prec RELATIONAL- { ExpBinary () (getTransSpan $1 $3) $2 $1 $3 }-| opCustom EXPRESSION %prec DEFINED_UNARY- { let TOpCustom span str = $1- in ExpUnary () (getTransSpan span $2) (UnCustom str) $2 }-| EXPRESSION opCustom EXPRESSION- { let TOpCustom _ str = $2- in ExpBinary () (getTransSpan $1 $3) (BinCustom str) $1 $3 }-| '(' EXPRESSION ')' { setSpan (getTransSpan $1 $3) $2 }-| NUMERIC_LITERAL { $1 }-| '(' EXPRESSION ',' EXPRESSION ')'- { ExpValue () (getTransSpan $1 $5) (ValComplex $2 $4) }-| LOGICAL_LITERAL { $1 }-| STRING { $1 }-| DATA_REF { $1 }-| IMPLIED_DO { $1 }-| '(/' EXPRESSION_LIST '/)'- { ExpInitialisation () (getTransSpan $1 $3) (fromReverseList $2) }-| operator '(' opCustom ')'- { let TOpCustom _ op = $3- in ExpValue () (getTransSpan $1 $4) (ValOperator op) }-| assignment { ExpValue () (getSpan $1) ValAssignment }-| '*' INTEGER_LITERAL { ExpReturnSpec () (getTransSpan $1 $2) $2 }--DATA_REFS :: { [ Expression A0 ] }-: DATA_REFS ',' DATA_REF { $3 : $1 }-| DATA_REF { [ $1 ] }--DATA_REF :: { Expression A0 }-: DATA_REF '%' PART_REF { ExpDataRef () (getTransSpan $1 $3) $1 $3 }-| PART_REF { $1 }--PART_REFS :: { [ Expression A0 ] }-: PART_REFS ',' PART_REF { $3 : $1 }-| PART_REF { [ $1 ] }--PART_REF :: { Expression A0 }-: VARIABLE { $1 }-| VARIABLE '(' ')'- { ExpFunctionCall () (getTransSpan $1 $3) $1 Nothing }-| VARIABLE '(' INDICIES ')'- { ExpSubscript () (getTransSpan $1 $4) $1 (fromReverseList $3) }-| VARIABLE '(' INDICIES ')' '(' INDICIES ')'- { let innerSub = ExpSubscript () (getTransSpan $1 $4) $1 (fromReverseList $3)- in ExpSubscript () (getTransSpan $1 $7) innerSub (fromReverseList $6) }--INDICIES :: { [ Index A0 ] }-: INDICIES ',' INDEX { $3 : $1 }-| INDEX { [ $1 ] }--INDEX :: { Index A0 }-: RANGE { $1 }-| RANGE ':' EXPRESSION- { let IxRange () s lower upper _ = $1- in IxRange () (getTransSpan s $3) lower upper (Just $3) }-| EXPRESSION { IxSingle () (getSpan $1) Nothing $1 }--- Following is only as an intermediate stage before having been turned into--- an argument by later transformation.-| id '=' EXPRESSION- { let TId s id = $1 in IxSingle () (getTransSpan $1 s) (Just id) $3 }--RANGE :: { Index A0 }-: ':' { IxRange () (getSpan $1) Nothing Nothing Nothing }-| ':' EXPRESSION { IxRange () (getTransSpan $1 $2) Nothing (Just $2) Nothing }-| EXPRESSION ':' { IxRange () (getTransSpan $1 $2) (Just $1) Nothing Nothing }-| EXPRESSION ':' EXPRESSION- { IxRange () (getTransSpan $1 $3) (Just $1) (Just $3) Nothing }--DO_SPECIFICATION :: { DoSpecification A0 }-: EXPRESSION_ASSIGNMENT_STATEMENT ',' EXPRESSION ',' EXPRESSION- { DoSpecification () (getTransSpan $1 $5) $1 $3 (Just $5) }-| EXPRESSION_ASSIGNMENT_STATEMENT ',' EXPRESSION- { DoSpecification () (getTransSpan $1 $3) $1 $3 Nothing }--IMPLIED_DO :: { Expression A0 }-: '(' EXPRESSION ',' DO_SPECIFICATION ')'- { let expList = AList () (getSpan $2) [ $2 ]- in ExpImpliedDo () (getTransSpan $1 $5) expList $4 }-| '(' EXPRESSION ',' EXPRESSION ',' DO_SPECIFICATION ')'- { let expList = AList () (getTransSpan $2 $4) [ $2, $4 ]- in ExpImpliedDo () (getTransSpan $1 $5) expList $6 }-| '(' EXPRESSION ',' EXPRESSION ',' EXPRESSION_LIST ',' DO_SPECIFICATION ')'- { let { exps = reverse $6;- expList = AList () (getTransSpan $2 exps) ($2 : $4 : reverse $6) }- in ExpImpliedDo () (getTransSpan $1 $9) expList $8 }--FORALL :: { Statement A0 }-: id ':' forall FORALL_HEADER {- let (TId s1 id) = $1 in- let (h,s2) = $4 in- StForall () (getTransSpan s1 s2) (Just id) h-}-| forall FORALL_HEADER {- let (h,s) = $2 in- StForall () (getTransSpan $1 s) Nothing h-}-| forall FORALL_HEADER FORALL_ASSIGNMENT_STMT {- let (h,_) = $2 in- StForallStatement () (getTransSpan $1 $3) h $3-}--FORALL_HEADER- :: { (ForallHeader A0, SrcSpan) }-FORALL_HEADER :- -- Standard simple forall header- '(' FORALL_TRIPLET_SPEC ')' { (ForallHeader [$2] Nothing, getTransSpan $1 $3) }- -- forall header with scale expression- | '(' '(' FORALL_TRIPLET_SPEC ')' ',' EXPRESSION ')'- { (ForallHeader [$3] (Just $6), getTransSpan $1 $7) }- -- multi forall header- | '(' FORALL_TRIPLET_SPEC_LIST_PLUS_STRIDE ')'- { (ForallHeader $2 Nothing, getTransSpan $1 $3) }- -- multi forall header with scale- | '(' FORALL_TRIPLET_SPEC_LIST_PLUS_STRIDE ',' EXPRESSION ')'- { (ForallHeader $2 (Just $4), getTransSpan $1 $5) }--FORALL_TRIPLET_SPEC_LIST_PLUS_STRIDE- :: { [(Name, Expression A0, Expression A0, Maybe (Expression A0))] }-FORALL_TRIPLET_SPEC_LIST_PLUS_STRIDE-: '(' FORALL_TRIPLET_SPEC ')' ',' FORALL_TRIPLET_SPEC_LIST_PLUS_STRIDE { $2 : $5 }-| {- empty -} { [] }--FORALL_TRIPLET_SPEC :: { (Name, Expression A0, Expression A0, Maybe (Expression A0)) }-FORALL_TRIPLET_SPEC-: NAME '=' EXPRESSION ':' EXPRESSION { ($1, $3, $5, Nothing) }-| NAME '=' EXPRESSION ':' EXPRESSION ',' EXPRESSION { ($1, $3, $5, Just $7) }--FORALL_ASSIGNMENT_STMT :: { Statement A0 }-FORALL_ASSIGNMENT_STMT :- EXPRESSION_ASSIGNMENT_STATEMENT { $1 }- | POINTER_ASSIGNMENT_STMT { $1 }--POINTER_ASSIGNMENT_STMT :: { Statement A0 }-POINTER_ASSIGNMENT_STMT :- DATA_REF '=>' EXPRESSION { StPointerAssign () (getTransSpan $1 $3) $1 $3 }--END_FORALL :: { Statement A0 }-END_FORALL :- endforall { StEndForall () (getSpan $1) Nothing }- | endforall id { let (TId s id) = $2 in StEndForall () (getTransSpan $1 s) (Just id)}--EXPRESSION_LIST :: { [ Expression A0 ] }-: EXPRESSION_LIST ',' EXPRESSION { $3 : $1 }-| EXPRESSION { [ $1 ] }--ARITHMETIC_SIGN :: { (SrcSpan, UnaryOp) }-: '-' { (getSpan $1, Minus) }-| '+' { (getSpan $1, Plus) }--RELATIONAL_OPERATOR :: { BinaryOp }-: '==' { EQ }-| '!=' { NE }-| '>' { GT }-| '>=' { GTE }-| '<' { LT }-| '<=' { LTE }--VARIABLE :: { Expression A0 }-: id { ExpValue () (getSpan $1) $ let (TId _ s) = $1 in ValVariable s }--NUMERIC_LITERAL :: { Expression A0 }-: INTEGER_LITERAL { $1 } | REAL_LITERAL { $1 }--INTEGERS :: { [ Expression A0 ] }-: INTEGERS ',' INTEGER_LITERAL { $3 : $1 }-| INTEGER_LITERAL { [ $1 ] }--INTEGER_LITERAL :: { Expression A0 }-: int- { let TIntegerLiteral s i = $1- in ExpValue () s $ ValInteger i Nothing }-| int '_' KIND_PARAM- { let TIntegerLiteral s i = $1- in ExpValue () s $ ValInteger i (Just $3) }-| boz { let TBozLiteral s b = $1 in ExpValue () s $ ValBoz b }--REAL_LITERAL :: { Expression A0 }-: float- { let TRealLiteral s r = $1- in ExpValue () s $ ValReal r Nothing }-| float '_' KIND_PARAM- { let TRealLiteral s r = $1- in ExpValue () s $ ValReal r (Just $3) }--LOGICAL_LITERAL :: { Expression A0 }-: bool- { let TLogicalLiteral s b = $1- in ExpValue () s (ValLogical b Nothing) }-| bool '_' KIND_PARAM- { let TLogicalLiteral s b = $1- in ExpValue () s (ValLogical b (Just $3)) }--KIND_PARAM :: { Expression A0 }-: INTEGER_LITERAL { $1 }-| VARIABLE { $1 }--STRING :: { Expression A0 }-: string { let TString s c = $1 in ExpValue () s $ ValString c }--cDATA :: { () } : {% pushContext ConData }-cIMPLICIT :: { () } : {% pushContext ConImplicit }-cNAMELIST :: { () } : {% pushContext ConNamelist }-cCOMMON :: { () } : {% pushContext ConCommon }-cPOP :: { () } : {% popContext }--{--unitNameCheck :: Token -> String -> Parse AlexInput Token ()-unitNameCheck (TId _ name1) name2- | name1 == name2 = return ()- | otherwise = fail "Unit name does not match the corresponding END statement."-unitNameCheck _ _ = return ()--parse = runParse programParser-defTransforms = defaultTransformations Fortran95--fortran95Parser- :: B.ByteString -> String -> ParseResult AlexInput Token (ProgramFile A0)-fortran95Parser = fortran95ParserWithTransforms defTransforms--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 = 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- parseState = initParseState sourceCode Fortran95 filename--parseError :: Token -> LexAction a-parseError token = do- parseState <- get-#ifdef DEBUG- tokens <- reverse <$> aiPreviousTokensInLine <$> getAlex-#endif- fail $ psFilename parseState ++ ": parsing failed. "- ++ specifics token-#ifdef DEBUG- ++ '\n' : show tokens-#endif- where specifics (TPause _) = "\nPAUSE statements are not supported in Fortran 95 or later. "- specifics (TAssign _) = "\nASSIGN statements are not supported in Fortran 95 or later. "- specifics _ = ""--}
+ src/Language/Fortran/Parser/Free/Fortran2003.y view
@@ -0,0 +1,1417 @@+-- -*- Mode: Haskell -*-+-- vim: ft=haskell+{+module Language.Fortran.Parser.Free.Fortran2003+ ( programParser+ , functionParser+ , blockParser+ , statementParser+ , expressionParser+ ) where++import Language.Fortran.Version+import Language.Fortran.Util.Position+import Language.Fortran.Parser.Monad+import Language.Fortran.Parser.Free.Lexer+import Language.Fortran.Parser.Free.Utils+import Language.Fortran.AST++import Prelude hiding ( EQ, LT, GT ) -- Same constructors exist in the AST+import Data.Either ( partitionEithers )++}++%name programParser PROGRAM+%name functionParser SUBPROGRAM_UNIT+%name blockParser BLOCK+%name statementParser STATEMENT+%name expressionParser EXPRESSION+%monad { LexAction }+%lexer { lexer } { TEOF _ }+%tokentype { Token }+%error { parseError }++%token+ id { TId _ _ }+ comment { TComment _ _ }+ string { TString _ _ }+ int { TIntegerLiteral _ _ }+ float { TRealLiteral _ _ }+ boz { TBozLiteral _ _ }+ '_' { TUnderscore _ }+ ',' { TComma _ }+ ',2' { TComma2 _ }+ ';' { TSemiColon _ }+ ':' { TColon _ }+ '::' { TDoubleColon _ }+ '=' { TOpAssign _ }+ '=>' { TArrow _ }+ '%' { TPercent _ }+ '(' { TLeftPar _ }+ '(2' { TLeftPar2 _ }+ ')' { TRightPar _ }+ '(/' { TLeftInitPar _ }+ '/)' { TRightInitPar _ }+ opCustom { TOpCustom _ _ }+ '**' { TOpExp _ }+ '+' { TOpPlus _ }+ '-' { TOpMinus _ }+ '*' { TStar _ }+ '/' { TOpDivision _ }+ slash { TSlash _ }+ or { TOpOr _ }+ and { TOpAnd _ }+ not { TOpNot _ }+ eqv { TOpEquivalent _ }+ neqv { TOpNotEquivalent _ }+ '<' { TOpLT _ }+ '<=' { TOpLE _ }+ '==' { TOpEQ _ }+ '!=' { TOpNE _ }+ '>' { TOpGT _ }+ '>=' { TOpGE _ }+ bool { TLogicalLiteral _ _ }+ program { TProgram _ }+ endProgram { TEndProgram _ }+ function { TFunction _ }+ endFunction { TEndFunction _ }+ result { TResult _ }+ pure { TPure _ }+ elemental { TElemental _ }+ recursive { TRecursive _ }+ subroutine { TSubroutine _ }+ endSubroutine { TEndSubroutine _ }+ blockData { TBlockData _ }+ endBlockData { TEndBlockData _ }+ module { TModule _ }+ endModule { TEndModule _ }+ contains { TContains _ }+ use { TUse _ }+ only { TOnly _ }+ import { TImport _ }+ abstract { TAbstract _ }+ interface { TInterface _ }+ endInterface { TEndInterface _ }+ moduleProcedure { TModuleProcedure _ }+ procedure { TProcedure _ }+ assignment { TAssignment _ }+ operator { TOperator _ }+ call { TCall _ }+ return { TReturn _ }+ entry { TEntry _ }+ include { TInclude _ }+ public { TPublic _ }+ private { TPrivate _ }+ protected { TProtected _ }+ parameter { TParameter _ }+ allocatable { TAllocatable _ }+ asynchronous { TAsynchronous _ }+ dimension { TDimension _ }+ external { TExternal _ }+ intent { TIntent _ }+ intrinsic { TIntrinsic _ }+ nonintrinsic { TNonIntrinsic _ }+ optional { TOptional _ }+ pointer { TPointer _ }+ save { TSave _ }+ target { TTarget _ }+ value { TValue _ }+ volatile { TVolatile _ }+ bind { TBind _ }+ 'c' { TC _ }+ name { TName _ }+ in { TIn _ }+ out { TOut _ }+ inout { TInOut _ }+ data { TData _ }+ namelist { TNamelist _ }+ implicit { TImplicit _ }+ equivalence { TEquivalence _ }+ common { TCommon _ }+ allocate { TAllocate _ }+ deallocate { TDeallocate _ }+ stat { TStat _ }+ errmsg { TErrMsg _ }+ source { TSource _ }+ nullify { TNullify _ }+ none { TNone _ }+ goto { TGoto _ }+ to { TTo _ }+ continue { TContinue _ }+ stop { TStop _ }+ do { TDo _ }+ enddo { TEndDo _ }+ while { TWhile _ }+ if { TIf _ }+ then { TThen _ }+ else { TElse _ }+ elsif { TElsif _ }+ endif { TEndIf _ }+ case { TCase _ }+ selectcase { TSelectCase _ }+ endselect { TEndSelect _ }+ associate { TAssociate _ }+ endassociate { TEndAssociate _ }+ default { TDefault _ }+ cycle { TCycle _ }+ exit { TExit _ }+ where { TWhere _ }+ elsewhere { TElsewhere _ }+ endwhere { TEndWhere _ }+ type { TType _ }+ endType { TEndType _ }+ class { TClass _ }+ enum { TEnum _ }+ enumerator { TEnumerator _ }+ endEnum { TEndEnum _ }+ sequence { TSequence _ }+ kind { TKind _ }+ len { TLen _ }+ integer { TInteger _ }+ real { TReal _ }+ doublePrecision { TDoublePrecision _ }+ logical { TLogical _ }+ character { TCharacter _ }+ complex { TComplex _ }+ open { TOpen _ }+ close { TClose _ }+ read { TRead _ }+ write { TWrite _ }+ print { TPrint _ }+ flush { TFlush _ }+ unit { TUnit _ }+ iostat { TIOStat _ }+ iomsg { TIOMsg _ }+ err { TErr _ }+ backspace { TBackspace _ }+ rewind { TRewind _ }+ inquire { TInquire _ }+ endfile { TEndfile _ }+ format { TFormat _ }+ blob { TBlob _ _ }+ end { TEnd _ }+ newline { TNewline _ }+ forall { TForall _ }+ endforall { TEndForall _ }+-- Precedence of operators++-- Level 6+%left opCustom++-- Level 5+%left eqv neqv+%left or+%left and+%right not++-- Level 4+%nonassoc '==' '!=' '>' '<' '>=' '<='+%nonassoc RELATIONAL++-- Level 3+%left CONCAT++-- Level 2+%left '+' '-'+%left '*' '/'+%right SIGN+%right '**'++-- Level 1+%right DEFINED_UNARY++-- Level 0+%left '%'++%%++maybe(p)+: p { Just $1 }+| {- empty -} { Nothing }++-- This rule is to ignore leading whitespace+PROGRAM :: { ProgramFile A0 }+: NEWLINE PROGRAM_INNER { $2 }+| PROGRAM_INNER { $1 }++PROGRAM_INNER :: { ProgramFile A0 }+: PROGRAM_UNITS { ProgramFile (MetaInfo { miVersion = Fortran2003, miFilename = "" }) (reverse $1) }+| {- empty -} { ProgramFile (MetaInfo { miVersion = Fortran2003, miFilename = "" }) [] }++PROGRAM_UNITS :: { [ ProgramUnit A0 ] }+: PROGRAM_UNITS PROGRAM_UNIT MAYBE_NEWLINE { $2 : $1 }+| PROGRAM_UNIT MAYBE_NEWLINE { [ $1 ] }++PROGRAM_UNIT :: { ProgramUnit A0 }+: program NAME NEWLINE BLOCKS MAYBE_SUBPROGRAM_UNITS PROGRAM_END+ {% do { unitNameCheck $6 $2;+ return $ PUMain () (getTransSpan $1 $6) (Just $2) (reverse $4) $5 } }+| module NAME NEWLINE BLOCKS MAYBE_SUBPROGRAM_UNITS MODULE_END+ {% do { unitNameCheck $6 $2;+ return $ PUModule () (getTransSpan $1 $6) $2 (reverse $4) $5 } }+| blockData NEWLINE BLOCKS BLOCK_DATA_END+ { PUBlockData () (getTransSpan $1 $4) Nothing (reverse $3) }+| blockData NAME NEWLINE BLOCKS BLOCK_DATA_END+ {% do { unitNameCheck $5 $2;+ return $ PUBlockData () (getTransSpan $1 $5) (Just $2) (reverse $4) } }+| SUBPROGRAM_UNIT { $1 }++MAYBE_SUBPROGRAM_UNITS :: { Maybe [ ProgramUnit A0 ] }+: contains NEWLINE SUBPROGRAM_UNITS { Just $ reverse $3 }+| {- Empty -} { Nothing }++SUBPROGRAM_UNITS :: { [ ProgramUnit A0 ] }+: SUBPROGRAM_UNITS SUBPROGRAM_UNIT NEWLINE { $2 : $1 }+| {- EMPTY -} { [ ] }++SUBPROGRAM_UNIT :: { ProgramUnit A0 }+: PREFIXES function NAME MAYBE_ARGUMENTS FUNC_SUFFIX MAYBE_COMMENT NEWLINE BLOCKS MAYBE_SUBPROGRAM_UNITS FUNCTION_END+ {% do { unitNameCheck $10 $3;+ let (pfxs, typeSpec) = case partitionEithers $1 of+ { (ps, t:_) -> (fromReverseList' ps, Just t)+ ; (ps, []) -> (fromReverseList' ps, Nothing) } in+ let (sfx, result) = $5 in+ let sfx' = fmap (\ s -> AList () (getSpan s) [s]) sfx in+ let ss = if null $1 then getTransSpan $2 $10 else getTransSpan (reverse $1) $10 in+ if validPrefixSuffix (pfxs, sfx') then+ return $ PUFunction () ss typeSpec (pfxs, sfx') $3 $4 result (reverse $8) $9+ else fail "Cannot specify elemental along with recursive and/or bind." } }+| PREFIXES subroutine NAME MAYBE_ARGUMENTS SUBR_SUFFIX MAYBE_COMMENT NEWLINE BLOCKS MAYBE_SUBPROGRAM_UNITS SUBROUTINE_END+ {% do { unitNameCheck $10 $3;+ (pfxs, typeSpec) <- case partitionEithers $1 of+ { (ps, t:_) -> fail "Subroutines cannot have return types."+ ; (ps, []) -> return (fromReverseList' ps, Nothing) };+ let sfx' = fmap (\ s -> AList () (getSpan s) [s]) $5 in+ let ss = if null $1 then getTransSpan $2 $10 else getTransSpan (reverse $1) $10 in+ if validPrefixSuffix (pfxs, sfx') then+ return $ PUSubroutine () ss (pfxs, sfx') $3 $4 (reverse $8) $9+ else fail "Cannot specify elemental along with recursive and/or bind." } }+| comment { let (TComment s c) = $1 in PUComment () s (Comment c) }++-- (Fortran2003) R1227, Fortran95 (...)+PREFIXES :: { [Either (Prefix A0) (TypeSpec A0)] }+: PREFIXES PREFIX { $2:$1 }+| {- EMPTY -} { [] }++-- (Fortran2003) R1228, Fortran95 (...)+PREFIX :: { Either (Prefix A0) (TypeSpec A0) }+: recursive { Left $ PfxRecursive () (getSpan $1) }+| elemental { Left $ PfxElemental () (getSpan $1) }+| pure { Left $ PfxPure () (getSpan $1) }+| TYPE_SPEC { Right $1 }++FUNC_SUFFIX :: { (Maybe (Suffix A0), Maybe (Expression A0)) }+: SUFFIX RESULT { (Just $1, Just $2) }+| RESULT SUFFIX { (Just $2, Just $1) }+| SUFFIX { (Just $1, Nothing) }+| RESULT { (Nothing, Just $1) }+| {- empty -} { (Nothing, Nothing) }++SUBR_SUFFIX :: { Maybe (Suffix A0) }+: SUFFIX { Just $1 }+| {- empty -} { Nothing }++-- (Fortran2003) R1229+SUFFIX :: { Suffix A0 }+-- (Fortran2003) R509+: bind '(' 'c' ',' name '=' EXPRESSION ')' { SfxBind () (getTransSpan $1 $8) (Just $7) }+| bind '(' 'c' ')' { SfxBind () (getTransSpan $1 $4) Nothing }++MAYBE_ARGUMENTS :: { Maybe (AList Expression A0) }+: '(' MAYBE_VARIABLES ')' { $2 }+| {- Nothing -} { Nothing }++RESULT :: { Expression A0 }+: result '(' VARIABLE ')' { $3 }++MAYBE_RESULT :: { Maybe (Expression A0) }+: RESULT { Just $1 }+| {- empty -} { Nothing}++PROGRAM_END :: { Token }+: end { $1 } | endProgram { $1 } | endProgram id { $2 }+MODULE_END :: { Token }+: end { $1 } | endModule { $1 } | endModule id { $2 }+FUNCTION_END :: { Token }+: end { $1 } | endFunction { $1 } | endFunction id { $2 }+SUBROUTINE_END :: { Token }+: end { $1 } | endSubroutine { $1 } | endSubroutine id { $2 }+BLOCK_DATA_END :: { Token }+: end { $1 } | endBlockData { $1 } | endBlockData id { $2 }+INTERFACE_END :: { Token }+: end { $1 } | endInterface { $1 } | endInterface id { $2 }++NAME :: { Name } : id { let (TId _ name) = $1 in name }++IMPORT_NAME_LIST :: { [Expression A0] }+: IMPORT_NAME_LIST ',' VARIABLE { $3 : $1 }+| VARIABLE { [ $1 ] }++BLOCKS :: { [ Block A0 ] } : BLOCKS BLOCK { $2 : $1 } | {- EMPTY -} { [ ] }++BLOCK :: { Block A0 }+: IF_BLOCK MAYBE_COMMENT NEWLINE { $1 }+| CASE_BLOCK MAYBE_COMMENT NEWLINE { $1 }+| ASSOCIATE_BLOCK MAYBE_COMMENT NEWLINE { $1 }+| INTEGER_LITERAL STATEMENT MAYBE_COMMENT NEWLINE+ { BlStatement () (getTransSpan $1 $2) (Just $1) $2 }+| STATEMENT MAYBE_COMMENT NEWLINE { BlStatement () (getSpan $1) Nothing $1 }+| ABSTRACTP interface MAYBE_EXPRESSION MAYBE_COMMENT NEWLINE SUBPROGRAM_UNITS2 MODULE_PROCEDURES INTERFACE_END MAYBE_COMMENT NEWLINE+ { BlInterface () (getTransSpan $2 $10) $3 $1 (reverse $6) (reverse $7) }+| ABSTRACTP interface MAYBE_EXPRESSION MAYBE_COMMENT NEWLINE MODULE_PROCEDURES INTERFACE_END MAYBE_COMMENT NEWLINE+ { BlInterface () (getTransSpan $2 $9) $3 $1 [ ] (reverse $6) }+| COMMENT_BLOCK { $1 }++IF_BLOCK :: { Block A0 }+: if '(' EXPRESSION ')' then MAYBE_COMMENT NEWLINE BLOCKS ELSE_BLOCKS+ { let { startSpan = getSpan $1;+ (endSpan, conds, blocks, endLabel) = $9;+ span = getTransSpan startSpan endSpan }+ in BlIf () span Nothing Nothing ((Just $3):conds) ((reverse $8):blocks) endLabel }+| id ':' if '(' EXPRESSION ')' then MAYBE_COMMENT NEWLINE BLOCKS ELSE_BLOCKS+ { let { TId startSpan startName = $1;+ (endSpan, conds, blocks, endLabel) = $11;+ span = getTransSpan startSpan endSpan }+ in BlIf () span Nothing (Just startName) ((Just $5):conds) ((reverse $10):blocks) endLabel }+| INTEGER_LITERAL if '(' EXPRESSION ')' then MAYBE_COMMENT NEWLINE BLOCKS ELSE_BLOCKS+ { let { startSpan = getSpan $1;+ startLabel = Just $1;+ (endSpan, conds, blocks, endLabel) = $10;+ span = getTransSpan startSpan endSpan }+ in BlIf () span startLabel Nothing ((Just $4):conds) ((reverse $9):blocks) endLabel }+| INTEGER_LITERAL id ':' if '(' EXPRESSION ')' then MAYBE_COMMENT NEWLINE BLOCKS ELSE_BLOCKS+ { let { startSpan = getSpan $1;+ startLabel = Just $1;+ TId _ startName = $2;+ (endSpan, conds, blocks, endLabel) = $12;+ span = getTransSpan startSpan endSpan }+ in BlIf () span startLabel (Just startName) ((Just $6):conds) ((reverse $11):blocks) endLabel }++ELSE_BLOCKS :: { (SrcSpan, [Maybe (Expression A0)], [[Block A0]], Maybe (Expression A0)) }+: maybe(INTEGER_LITERAL) elsif '(' EXPRESSION ')' then MAYBE_COMMENT NEWLINE BLOCKS ELSE_BLOCKS+ { let (endSpan, conds, blocks, endLabel) = $10+ in (endSpan, Just $4 : conds, reverse $9 : blocks, endLabel) }+| maybe(INTEGER_LITERAL) else MAYBE_COMMENT NEWLINE BLOCKS END_IF+ { let (endSpan, endLabel) = $6+ in (endSpan, [Nothing], [reverse $5], endLabel) }+| END_IF { let (endSpan, endLabel) = $1 in (endSpan, [], [], endLabel) }++END_IF :: { (SrcSpan, Maybe (Expression A0)) }+: endif { (getSpan $1, Nothing) }+| endif id { (getSpan $2, Nothing) }+| INTEGER_LITERAL endif { (getSpan $2, Just $1) }+| INTEGER_LITERAL endif id { (getSpan $3, Just $1) }++CASE_BLOCK :: { Block A0 }+: selectcase '(' EXPRESSION ')' MAYBE_COMMENT NEWLINE CASES+ { let { (caseRanges, blocks, endLabel, endSpan) = $7;+ span = getTransSpan $1 endSpan }+ in BlCase () span Nothing Nothing $3 caseRanges blocks endLabel }+| INTEGER_LITERAL selectcase '(' EXPRESSION ')' MAYBE_COMMENT NEWLINE CASES+ { let { (caseRanges, blocks, endLabel, endSpan) = $8;+ span = getTransSpan $1 endSpan }+ in BlCase () span (Just $1) Nothing $4 caseRanges blocks endLabel }+| id ':' selectcase '(' EXPRESSION ')' MAYBE_COMMENT NEWLINE CASES+ { let { (caseRanges, blocks, endLabel, endSpan) = $9;+ TId s startName = $1;+ span = getTransSpan s endSpan }+ in BlCase () span Nothing (Just startName) $5 caseRanges blocks endLabel }+| INTEGER_LITERAL id ':' selectcase '(' EXPRESSION ')' MAYBE_COMMENT NEWLINE CASES+ { let { (caseRanges, blocks, endLabel, endSpan) = $10;+ TId s startName = $2;+ span = getTransSpan s endSpan }+ in BlCase () span (Just $1) (Just startName) $6 caseRanges blocks endLabel }++-- We store line comments as statements, but this raises an issue: we have+-- nowhere to place comments after a SELECT CASE but before a CASE. So we drop+-- them. The inner CASES_ rule does /not/ use this, because comments can always+-- be parsed as belonging to to the above CASE block.+CASES :: { ([Maybe (AList Index A0)], [[Block A0]], Maybe (Expression A0), SrcSpan) }+: COMMENT_BLOCK CASES_ { $2 }+| CASES_ { $1 }++CASES_ :: { ([Maybe (AList Index A0)], [[Block A0]], Maybe (Expression A0), SrcSpan) }+: maybe(INTEGER_LITERAL) case '(' INDICIES ')' MAYBE_COMMENT NEWLINE BLOCKS CASES_+ { let (scrutinees, blocks, endLabel, endSpan) = $9+ in (Just (fromReverseList $4) : scrutinees, reverse $8 : blocks, endLabel, endSpan) }+| maybe(INTEGER_LITERAL) case default MAYBE_COMMENT NEWLINE BLOCKS END_SELECT+ { let (endLabel, endSpan) = $7+ in ([Nothing], [$6], endLabel, endSpan) }+| END_SELECT+ { let (endLabel, endSpan) = $1+ in ([], [], endLabel, endSpan) }++END_SELECT :: { (Maybe (Expression A0), SrcSpan) }+: maybe(INTEGER_LITERAL) endselect maybe(id)+ { ($1, maybe (getSpan $2) getSpan $3) }++ASSOCIATE_BLOCK :: { Block A0 }+: INTEGER_LITERAL id ':' associate '(' ABBREVIATIONS ')' MAYBE_COMMENT NEWLINE BLOCKS END_ASSOCIATE+ { let { startSpan = getSpan $1;+ mLabel = Just $1;+ TId _ name = $2;+ mName = Just name;+ abbrevs = fromReverseList $6;+ body = reverse $10;+ (endSpan, mEndLabel) = $11;+ span = getTransSpan startSpan endSpan }+ in BlAssociate () span mLabel mName abbrevs body mEndLabel }+| INTEGER_LITERAL associate '(' ABBREVIATIONS ')' MAYBE_COMMENT NEWLINE BLOCKS END_ASSOCIATE+ { let { startSpan = getSpan $1;+ mLabel = Just $1;+ mName = Nothing;+ abbrevs = fromReverseList $4;+ body = reverse $8;+ (endSpan, mEndLabel) = $9;+ span = getTransSpan startSpan endSpan }+ in BlAssociate () span mLabel mName abbrevs body mEndLabel }+| id ':' associate '(' ABBREVIATIONS ')' MAYBE_COMMENT NEWLINE BLOCKS END_ASSOCIATE+ { let { startSpan = getSpan $1;+ TId _ name = $1;+ mLabel = Nothing;+ mName = Just name;+ abbrevs = fromReverseList $5;+ body = reverse $9;+ (endSpan, mEndLabel) = $10;+ span = getTransSpan startSpan endSpan }+ in BlAssociate () span mLabel mName abbrevs body mEndLabel }+| associate '(' ABBREVIATIONS ')' MAYBE_COMMENT NEWLINE BLOCKS END_ASSOCIATE+ { let { startSpan = getSpan $1;+ mLabel = Nothing;+ mName = Nothing;+ abbrevs = fromReverseList $3;+ body = reverse $7;+ (endSpan, mEndLabel) = $8;+ span = getTransSpan startSpan endSpan }+ in BlAssociate () span mLabel mName abbrevs body mEndLabel }++-- TODO: Copied verbatim from END_IF. Should attempt to functionalise.+END_ASSOCIATE :: { (SrcSpan, Maybe (Expression A0)) }+: endassociate { (getSpan $1, Nothing) }+| endassociate id { (getSpan $2, Nothing) }+| INTEGER_LITERAL endassociate { (getSpan $2, Just $1) }+| INTEGER_LITERAL endassociate id { (getSpan $3, Just $1) }++-- (var (ExpValue (ValVariable)), assoc. expr)+ABBREVIATIONS :: { [(ATuple Expression Expression A0)] }+: ABBREVIATIONS ',' ABBREVIATION { $3 : $1 }+| ABBREVIATION { [ $1 ] }++ABBREVIATION :: { ATuple Expression Expression A0 }+: VARIABLE '=>' EXPRESSION { ATuple () (getTransSpan $1 $3) $1 $3 }++ABSTRACTP :: { Bool }+: abstract { True }+| {- EMPTY -} { False }++MAYBE_EXPRESSION :: { Maybe (Expression A0) }+: EXPRESSION { Just $1 }+| {- EMPTY -} { Nothing }++MAYBE_COMMENT :: { Maybe Token }+: comment { Just $1 }+| {- EMPTY -} { Nothing }++SUBPROGRAM_UNITS2 :: { [ ProgramUnit A0 ] }+: SUBPROGRAM_UNITS SUBPROGRAM_UNIT NEWLINE { $2 : $1 }++MODULE_PROCEDURES :: { [ Block A0 ] }+: MODULE_PROCEDURES MODULE_PROCEDURE { $2 : $1 }+| MODULE_PROCEDURES MODULE_PROCEDURE COMMENT_BLOCK { $3 : $2 : $1 }+| { [ ] }++MODULE_PROCEDURE :: { Block A0 }+: moduleProcedure VARIABLES MAYBE_COMMENT NEWLINE+ { let { al = fromReverseList $2;+ st = StModuleProcedure () (getTransSpan $1 al) (fromReverseList $2) }+ in BlStatement () (getTransSpan $1 $4) Nothing st }++COMMENT_BLOCK :: { Block A0 }+: comment NEWLINE { let (TComment s c) = $1 in BlComment () s (Comment c) }++MAYBE_NEWLINE :: { Maybe Token } : NEWLINE { Just $1 } | {- EMPTY -} { Nothing }++NEWLINE :: { Token }+: NEWLINE newline { $1 }+| NEWLINE ';' { $1 }+| newline { $1 }+| ';' { $1 }++STATEMENT :: { Statement A0 }+: NONEXECUTABLE_STATEMENT { $1 }+| EXECUTABLE_STATEMENT { $1 }++EXPRESSION_ASSIGNMENT_STATEMENT :: { Statement A0 }+: DATA_REF '=' EXPRESSION { StExpressionAssign () (getTransSpan $1 $3) $1 $3 }++NONEXECUTABLE_STATEMENT :: { Statement A0 }+: DECLARATION_STATEMENT { $1 }+| intent '(' INTENT_CHOICE ')' MAYBE_DCOLON EXPRESSION_LIST+ { let expAList = fromReverseList $6+ in StIntent () (getTransSpan $1 expAList) $3 expAList }+| optional MAYBE_DCOLON EXPRESSION_LIST+ { let expAList = fromReverseList $3+ in StOptional () (getTransSpan $1 expAList) expAList }+| public MAYBE_DCOLON EXPRESSION_LIST+ { let expAList = fromReverseList $3+ in StPublic () (getTransSpan $1 expAList) (Just expAList) }+| public { StPublic () (getSpan $1) Nothing }+| private MAYBE_DCOLON EXPRESSION_LIST+ { let expAList = fromReverseList $3+ in StPrivate () (getTransSpan $1 expAList) (Just expAList) }+| private { StPrivate () (getSpan $1) Nothing }+| protected MAYBE_DCOLON EXPRESSION_LIST+ { let expAList = fromReverseList $3+ in StProtected () (getTransSpan $1 expAList) (Just expAList) }+| protected { StProtected () (getSpan $1) Nothing }+| save MAYBE_DCOLON SAVE_ARGS+ { let saveAList = (fromReverseList $3)+ in StSave () (getTransSpan $1 saveAList) (Just saveAList) }+| save { StSave () (getSpan $1) Nothing }+| procedure '(' MAYBE_PROC_INTERFACE ')' ',' ATTRIBUTE_SPEC '::' PROC_DECLS+ { let declAList = fromReverseList $8+ in StProcedure () (getTransSpan $1 $8) $3 (Just $6) declAList }+| procedure '(' MAYBE_PROC_INTERFACE ')' MAYBE_DCOLON PROC_DECLS+ { let declAList = fromReverseList $6+ in StProcedure () (getTransSpan $1 $6) $3 Nothing declAList }+| dimension MAYBE_DCOLON INITIALIZED_DECLARATOR_LIST+ { let declAList = fromReverseList $3+ in StDimension () (getTransSpan $1 declAList) declAList }+| allocatable MAYBE_DCOLON INITIALIZED_DECLARATOR_LIST+ { let declAList = fromReverseList $3+ in StAllocatable () (getTransSpan $1 declAList) declAList }+| asynchronous MAYBE_DCOLON INITIALIZED_DECLARATOR_LIST+ { let declAList = fromReverseList $3+ in StAsynchronous () (getTransSpan $1 declAList) declAList }+| pointer MAYBE_DCOLON INITIALIZED_DECLARATOR_LIST+ { let declAList = fromReverseList $3+ in StPointer () (getTransSpan $1 declAList) declAList }+| target MAYBE_DCOLON INITIALIZED_DECLARATOR_LIST+ { let declAList = fromReverseList $3+ in StTarget () (getTransSpan $1 declAList) declAList }+| value MAYBE_DCOLON INITIALIZED_DECLARATOR_LIST+ { let declAList = fromReverseList $3+ in StValue () (getTransSpan $1 declAList) declAList }+| volatile MAYBE_DCOLON INITIALIZED_DECLARATOR_LIST+ { let declAList = fromReverseList $3+ in StVolatile () (getTransSpan $1 declAList) declAList }+| data cDATA DATA_GROUPS cPOP+ { let dataAList = fromReverseList $3+ in StData () (getTransSpan $1 dataAList) dataAList }+| parameter '(' PARAMETER_ASSIGNMENTS ')'+ { let declAList = fromReverseList $3+ in StParameter () (getTransSpan $1 $4) declAList }+| implicit none { StImplicit () (getTransSpan $1 $2) Nothing }+| implicit cIMPLICIT IMP_LISTS cPOP+ { let impAList = fromReverseList $3+ in StImplicit () (getTransSpan $1 impAList) $ Just $ impAList }+| namelist cNAMELIST NAMELISTS cPOP+ { let nameALists = fromReverseList $3+ in StNamelist () (getTransSpan $1 nameALists) nameALists }+| equivalence EQUIVALENCE_GROUPS+ { let eqALists = fromReverseList $2+ in StEquivalence () (getTransSpan $1 eqALists) eqALists }+| common cCOMMON COMMON_GROUPS cPOP+ { let commonAList = fromReverseList $3+ in StCommon () (getTransSpan $1 commonAList) commonAList }+| external MAYBE_DCOLON VARIABLES+ { let alist = fromReverseList $3+ in StExternal () (getTransSpan $1 alist) alist }+| intrinsic MAYBE_DCOLON VARIABLES+ { let alist = fromReverseList $3+ in StIntrinsic () (getTransSpan $1 alist) alist }+| use MODULE_NATURE VARIABLE { StUse () (getTransSpan $1 $3) $3 $2 Permissive Nothing }+| use MODULE_NATURE VARIABLE ',' RENAME_LIST+ { let alist = fromReverseList $5+ in StUse () (getTransSpan $1 alist) $3 $2 Permissive (Just alist) }+| use MODULE_NATURE VARIABLE ',' only ':' MAYBE_RENAME_LIST+ { StUse () (getTransSpan $1 ($6, $7)) $3 $2 Exclusive $7 }+| entry VARIABLE MAYBE_RESULT+ { StEntry () (getTransSpan $1 $ maybe (getSpan $2) getSpan $3) $2 Nothing $3 }+| entry VARIABLE '(' ')' MAYBE_RESULT+ { StEntry () (getTransSpan $1 $ maybe (getSpan $4) getSpan $5) $2 Nothing $5 }+| entry VARIABLE '(' VARIABLES ')' MAYBE_RESULT+ { StEntry () (getTransSpan $1 $ maybe (getSpan $5) getSpan $6) $2 (Just $ fromReverseList $4) $6 }+| sequence { StSequence () (getSpan $1) }+| type ATTRIBUTE_LIST '::' id+ { let { TId span id = $4;+ alist = if null $2 then Nothing else (Just . fromReverseList) $2 }+ in StType () (getTransSpan $1 span) alist id }+| type id+ { let TId span id = $2 in StType () (getTransSpan $1 span) Nothing id }+| endType { StEndType () (getSpan $1) Nothing }+| endType id+ { let TId span id = $2 in StEndType () (getTransSpan $1 span) (Just id) }+-- R461-R464+| enum ',' bind '(' 'c' ')' { StEnum () (getTransSpan $1 $6) }+| enumerator MAYBE_DCOLON ENUMERATOR_LIST { StEnumerator () (getTransSpan $1 $3) (fromReverseList $3) }+| endEnum { StEndEnum () (getSpan $1) }+| include STRING { StInclude () (getTransSpan $1 $2) $2 Nothing }+-- R1209+| import '::' IMPORT_NAME_LIST { StImport () (getTransSpan $1 $3) (fromReverseList $3) }+| import IMPORT_NAME_LIST { StImport () (getTransSpan $1 $2) (fromReverseList $2) }+-- Following is a fake node to make arbitrary FORMAT statements parsable.+-- Must be fixed in the future. TODO+| format blob+ { let TBlob s blob = $2 in StFormatBogus () (getTransSpan $1 s) blob }++ENUMERATOR_LIST :: { [Declarator A0] }+: ENUMERATOR_LIST ',' ENUMERATOR { $3:$1 }+| ENUMERATOR { [$1] }++-- R463+ENUMERATOR :: { Declarator A0 }+: PARAMETER_ASSIGNMENT { $1 }+| VARIABLE { Declarator () (getSpan $1) $1 ScalarDecl Nothing Nothing }++MAYBE_PROC_INTERFACE :: { Maybe (ProcInterface A0) }+: TYPE_SPEC { Just $ ProcInterfaceType () (getSpan $1) $1 }+| VARIABLE { Just $ ProcInterfaceName () (getSpan $1) $1 }+| {- EMPTY -} { Nothing }++PROC_DECLS :: { [ProcDecl A0] }+: PROC_DECLS ',' PROC_DECL { $3 : $1 }+| PROC_DECL { [ $1 ] }++PROC_DECL :: { ProcDecl A0 }+: VARIABLE '=>' EXPRESSION { ProcDecl () (getTransSpan $1 $3) $1 (Just $3) }+| VARIABLE { ProcDecl () (getSpan $1) $1 Nothing }++MODULE_NATURE :: { Maybe ModuleNature }+: ',' intrinsic '::' { Just ModIntrinsic }+| ',' nonintrinsic '::' { Just ModNonIntrinsic }+| '::' { Nothing }+| {- empty -} { Nothing }++EXECUTABLE_STATEMENT :: { Statement A0 }+: allocate '(' MAYBE_TYPE_SPEC DATA_REFS MAYBE_ALLOC_OPT_LIST ')'+ { StAllocate () (getTransSpan $1 $6) $3 (fromReverseList $4) $5 }+| nullify '(' DATA_REFS ')'+ { StNullify () (getTransSpan $1 $4) (fromReverseList $3) }+| deallocate '(' DATA_REFS MAYBE_ALLOC_OPT_LIST ')'+ { StDeallocate () (getTransSpan $1 $5) (fromReverseList $3) $4 }+| EXPRESSION_ASSIGNMENT_STATEMENT { $1 }+| POINTER_ASSIGNMENT_STMT { $1 }+| where '(' EXPRESSION ')' EXPRESSION_ASSIGNMENT_STATEMENT+ { StWhere () (getTransSpan $1 $5) $3 $5 }+| id ':' where '(' EXPRESSION ')' { let (TId s1 id) = $1 in StWhereConstruct () (getTransSpan $1 $6) (Just id) $5 }+| where '(' EXPRESSION ')' { StWhereConstruct () (getTransSpan $1 $4) Nothing $3 }+| elsewhere '(' EXPRESSION ')' id { let TId _ id = $5 in StElsewhere () (getTransSpan $1 $5) (Just id) (Just $3) }+| elsewhere '(' EXPRESSION ')' { StElsewhere () (getTransSpan $1 $4) Nothing (Just $3) }+| elsewhere id { let TId _ id = $2 in StElsewhere () (getTransSpan $1 $2) (Just id) Nothing }+| elsewhere { StElsewhere () (getSpan $1) Nothing Nothing }+| endwhere id { let TId _ id = $2 in StEndWhere () (getTransSpan $1 $2) (Just id) }+| endwhere { StEndWhere () (getSpan $1) Nothing }+| if '(' EXPRESSION ')' INTEGER_LITERAL ',' INTEGER_LITERAL ',' INTEGER_LITERAL+ { StIfArithmetic () (getTransSpan $1 $9) $3 $5 $7 $9 }+| do { StDo () (getSpan $1) Nothing Nothing Nothing }+| id ':' do+ { let TId s id = $1+ in StDo () (getTransSpan s $3) (Just id) Nothing Nothing }+| do INTEGER_LITERAL MAYBE_COMMA DO_SPECIFICATION+ { StDo () (getTransSpan $1 $4) Nothing (Just $2) (Just $4) }+| do DO_SPECIFICATION { StDo () (getTransSpan $1 $2) Nothing Nothing (Just $2) }+| id ':' do DO_SPECIFICATION+ { let TId s id = $1+ in StDo () (getTransSpan s $4) (Just id) Nothing (Just $4) }+| do INTEGER_LITERAL MAYBE_COMMA while '(' EXPRESSION ')'+ { StDoWhile () (getTransSpan $1 $7) Nothing (Just $2) $6 }+| do while '(' EXPRESSION ')'+ { StDoWhile () (getTransSpan $1 $5) Nothing Nothing $4 }+| id ':' do while '(' EXPRESSION ')'+ { let TId s id = $1+ in StDoWhile () (getTransSpan s $7) (Just id) Nothing $6 }+| enddo { StEnddo () (getSpan $1) Nothing }+| enddo id+ { let TId s id = $2 in StEnddo () (getTransSpan $1 s) (Just id) }+| cycle { StCycle () (getSpan $1) Nothing }+| cycle VARIABLE { StCycle () (getTransSpan $1 $2) (Just $2) }+| exit { StExit () (getSpan $1) Nothing }+| exit VARIABLE { StExit () (getTransSpan $1 $2) (Just $2) }+-- GO TO label+| goto INTEGER_LITERAL { StGotoUnconditional () (getTransSpan $1 $2) $2 }+-- GO TO label-list [,] scalar-int-expression+| goto '(' INTEGERS ')' MAYBE_COMMA EXPRESSION+ { StGotoComputed () (getTransSpan $1 $6) (fromReverseList $3) $6 }+| continue { StContinue () (getSpan $1) }+| stop { StStop () (getSpan $1) Nothing }+| stop EXPRESSION { StStop () (getTransSpan $1 $2) (Just $2) }+| if '(' EXPRESSION ')' EXECUTABLE_STATEMENT+ { StIfLogical () (getTransSpan $1 $5) $3 $5 }+| read CILIST IN_IOLIST+ { let alist = fromReverseList $3+ in StRead () (getTransSpan $1 alist) $2 (Just alist) }+| read CILIST { StRead () (getTransSpan $1 $2) $2 Nothing }+| read FORMAT_ID ',' IN_IOLIST+ { let alist = fromReverseList $4+ in StRead2 () (getTransSpan $1 alist) $2 (Just alist) }+| read FORMAT_ID { StRead2 () (getTransSpan $1 $2) $2 Nothing }+| write CILIST OUT_IOLIST+ { let alist = fromReverseList $3+ in StWrite () (getTransSpan $1 alist) $2 (Just alist) }+| write CILIST { StWrite () (getTransSpan $1 $2) $2 Nothing }+| print FORMAT_ID ',' OUT_IOLIST+ { let alist = fromReverseList $4+ in StPrint () (getTransSpan $1 alist) $2 (Just alist) }+| print FORMAT_ID { StPrint () (getTransSpan $1 $2) $2 Nothing }+| open CILIST { StOpen () (getTransSpan $1 $2) $2 }+| close CILIST { StClose () (getTransSpan $1 $2) $2 }+| inquire CILIST { StInquire () (getTransSpan $1 $2) $2 }+| rewind CILIST { StRewind () (getTransSpan $1 $2) $2 }+| rewind UNIT { StRewind2 () (getTransSpan $1 $2) $2 }+| endfile CILIST { StEndfile () (getTransSpan $1 $2) $2 }+| endfile UNIT { StEndfile2 () (getTransSpan $1 $2) $2 }+| backspace CILIST { StBackspace () (getTransSpan $1 $2) $2 }+| backspace UNIT { StBackspace2 () (getTransSpan $1 $2) $2 }+| flush INTEGER_LITERAL { StFlush () (getTransSpan $1 $2) (AList () (getSpan $2) [FSUnit () (getSpan $2) $2]) }+| flush '(' FLUSH_SPEC_LIST ')' { StFlush () (getTransSpan $1 $4) (fromReverseList $3) }+| call VARIABLE { StCall () (getTransSpan $1 $2) $2 Nothing }+| call VARIABLE '(' ')' { StCall () (getTransSpan $1 $4) $2 Nothing }+| call VARIABLE '(' ARGUMENTS ')'+ { let alist = fromReverseList $4+ in StCall () (getTransSpan $1 $5) $2 (Just alist) }+| return { StReturn () (getSpan $1) Nothing }+| return EXPRESSION { StReturn () (getTransSpan $1 $2) (Just $2) }+| FORALL { $1 }+| END_FORALL { $1 }++ARGUMENTS :: { [ Argument A0 ] }+: ARGUMENTS ',' ARGUMENT { $3 : $1 }+| ARGUMENT { [ $1 ] }++ARGUMENT :: { Argument A0 }+: id '=' EXPRESSION+ { let TId span keyword = $1+ in Argument () (getTransSpan span $3) (Just keyword) (ArgExpr $3) }+| '(' VARIABLE ')'+ { let ExpValue _ _ (ValVariable v) = $2+ in Argument () (getTransSpan $1 $3) Nothing (ArgExprVar () (getSpan $2) v) }+| EXPRESSION+ { Argument () (getSpan $1) Nothing (ArgExpr $1) }++MAYBE_RENAME_LIST :: { Maybe (AList Use A0) }+: RENAME_LIST { Just $ fromReverseList $1 }+| {- empty -} { Nothing }++RENAME_LIST :: { [ Use A0 ] }+: RENAME_LIST ',' RENAME { $3 : $1 }+| RENAME { [ $1 ] }++RENAME :: { Use A0 }+: VARIABLE '=>' VARIABLE { UseRename () (getTransSpan $1 $3) $1 $3 }+| VARIABLE { UseID () (getSpan $1) $1 }+| operator '(' opCustom ')'+ { let TOpCustom ss op = $3+ in UseID () (getTransSpan $1 $4) (ExpValue () ss (ValOperator op)) }+| assignment { UseID () (getSpan $1) (ExpValue () (getSpan $1) ValAssignment) }++MAYBE_DCOLON :: { () } : '::' { () } | {- EMPTY -} { () }++FORMAT_ID :: { Expression A0 }+: FORMAT_ID '/' '/' FORMAT_ID %prec CONCAT+ { ExpBinary () (getTransSpan $1 $4) Concatenation $1 $4 }+| INTEGER_LITERAL { $1 }+| STRING { $1 }+| DATA_REF { $1 }+| '*' { ExpValue () (getSpan $1) ValStar }++UNIT :: { Expression A0 }+: INTEGER_LITERAL { $1 }+| DATA_REF { $1 }+| '*' { ExpValue () (getSpan $1) ValStar }++{- R928 -}+FLUSH_SPEC_LIST :: { [ FlushSpec A0 ] }+: FLUSH_SPEC_LIST ',' FLUSH_SPEC { $3 : $1 }+| FLUSH_SPEC { [ $1 ] }++{- R928 -}+FLUSH_SPEC :: { FlushSpec A0 }+: EXPRESSION { FSUnit () (getSpan $1) $1 }+| unit '=' EXPRESSION { FSUnit () (getTransSpan $1 $3) $3 }+| iostat '=' EXPRESSION { FSIOStat () (getTransSpan $1 $3) $3 }+| iomsg '=' EXPRESSION { FSIOMsg () (getTransSpan $1 $3) $3 }+| err '=' EXPRESSION { FSErr () (getTransSpan $1 $3) $3 }++CILIST :: { AList ControlPair A0 }+: '(' CILIST_ELEMENT ',' FORMAT_ID ',' CILIST_PAIRS ')'+ { let { cp1 = ControlPair () (getSpan $2) Nothing $2;+ cp2 = ControlPair () (getSpan $4) Nothing $4;+ tail = fromReverseList $6 }+ in setSpan (getTransSpan $1 $7) $ cp1 `aCons` cp2 `aCons` tail }+| '(' CILIST_ELEMENT ',' FORMAT_ID ')'+ { let { cp1 = ControlPair () (getSpan $2) Nothing $2;+ cp2 = ControlPair () (getSpan $4) Nothing $4 }+ in AList () (getTransSpan $1 $5) [ cp1, cp2 ] }+| '(' CILIST_ELEMENT ',' CILIST_PAIRS ')'+ { let { cp1 = ControlPair () (getSpan $2) Nothing $2;+ tail = fromReverseList $4 }+ in setSpan (getTransSpan $1 $5) $ cp1 `aCons` tail }+| '(' CILIST_ELEMENT ')'+ { let cp1 = ControlPair () (getSpan $2) Nothing $2+ in AList () (getTransSpan $1 $3) [ cp1 ] }+| '(' CILIST_PAIRS ')' { fromReverseList $2 }++CILIST_PAIRS :: { [ ControlPair A0 ] }+: CILIST_PAIRS ',' CILIST_PAIR { $3 : $1 }+| CILIST_PAIR { [ $1 ] }++CILIST_PAIR :: { ControlPair A0 }+: id '=' CILIST_ELEMENT+ { let (TId s id) = $1 in ControlPair () (getTransSpan s $3) (Just id) $3 }++CILIST_ELEMENT :: { Expression A0 }+: CI_EXPRESSION { $1 }+| '*' { ExpValue () (getSpan $1) ValStar }++CI_EXPRESSION :: { Expression A0 }+: CI_EXPRESSION '+' CI_EXPRESSION+ { ExpBinary () (getTransSpan $1 $3) Addition $1 $3 }+| CI_EXPRESSION '-' CI_EXPRESSION+ { ExpBinary () (getTransSpan $1 $3) Subtraction $1 $3 }+| CI_EXPRESSION '*' CI_EXPRESSION+ { ExpBinary () (getTransSpan $1 $3) Multiplication $1 $3 }+| CI_EXPRESSION '/' CI_EXPRESSION+ { ExpBinary () (getTransSpan $1 $3) Division $1 $3 }+| CI_EXPRESSION '**' CI_EXPRESSION+ { ExpBinary () (getTransSpan $1 $3) Exponentiation $1 $3 }+| CI_EXPRESSION '/' '/' CI_EXPRESSION %prec CONCAT+ { ExpBinary () (getTransSpan $1 $4) Concatenation $1 $4 }+| ARITHMETIC_SIGN CI_EXPRESSION %prec SIGN+ { ExpUnary () (getTransSpan (fst $1) $2) (snd $1) $2 }+| CI_EXPRESSION or CI_EXPRESSION+ { ExpBinary () (getTransSpan $1 $3) Or $1 $3 }+| CI_EXPRESSION and CI_EXPRESSION+ { ExpBinary () (getTransSpan $1 $3) And $1 $3 }+| not CI_EXPRESSION+ { ExpUnary () (getTransSpan $1 $2) Not $2 }+| CI_EXPRESSION eqv CI_EXPRESSION+ { ExpBinary () (getTransSpan $1 $3) Equivalent $1 $3 }+| CI_EXPRESSION neqv CI_EXPRESSION+ { ExpBinary () (getTransSpan $1 $3) NotEquivalent $1 $3 }+| CI_EXPRESSION RELATIONAL_OPERATOR CI_EXPRESSION %prec RELATIONAL+ { ExpBinary () (getTransSpan $1 $3) $2 $1 $3 }+| opCustom CI_EXPRESSION %prec DEFINED_UNARY+ { let TOpCustom span str = $1+ in ExpUnary () (getTransSpan span $2) (UnCustom str) $2 }+| CI_EXPRESSION opCustom CI_EXPRESSION+ { let TOpCustom _ str = $2+ in ExpBinary () (getTransSpan $1 $3) (BinCustom str) $1 $3 }+| '(' CI_EXPRESSION ')' { setSpan (getTransSpan $1 $3) $2 }+| INTEGER_LITERAL { $1 }+| LOGICAL_LITERAL { $1 }+| STRING { $1 }+| DATA_REF { $1 }++MAYBE_ALLOC_OPT_LIST :: { Maybe (AList AllocOpt A0) }+: ',' ALLOC_OPT_LIST { Just $ fromReverseList $2 }+| {- empty -} { Nothing }++ALLOC_OPT_LIST :: { [ AllocOpt A0 ] }+: ALLOC_OPT_LIST ',' ALLOC_OPT { $3 : $1 }+| ALLOC_OPT { [ $1 ] }++{- R624 -}+ALLOC_OPT :: { AllocOpt A0 }+: stat '=' EXPRESSION { AOStat () (getTransSpan $1 $3) $3 }+| errmsg '=' EXPRESSION { AOErrMsg () (getTransSpan $1 $3) $3 }+| source '=' EXPRESSION { AOSource () (getTransSpan $1 $3) $3 }++IN_IOLIST :: { [ Expression A0 ] }+: IN_IOLIST ',' IN_IO_ELEMENT { $3 : $1}+| IN_IO_ELEMENT { [ $1 ] }++IN_IO_ELEMENT :: { Expression A0 }+: DATA_REF { $1 }+| '(' IN_IOLIST ',' DO_SPECIFICATION ')'+ { ExpImpliedDo () (getTransSpan $1 $5) (fromReverseList $2) $4 }++OUT_IOLIST :: { [ Expression A0 ] }+: OUT_IOLIST ',' EXPRESSION { $3 : $1}+| EXPRESSION { [ $1 ] }++COMMON_GROUPS :: { [ CommonGroup A0 ] }+: COMMON_GROUPS COMMON_GROUP { $2 : $1 }+| COMMON_GROUPS ',2' COMMON_GROUP { $3 : $1 }+| INIT_COMMON_GROUP { [ $1 ] }++COMMON_GROUP :: { CommonGroup A0 }+: COMMON_NAME UNINITIALIZED_DECLARATOR_LIST+ { let alist = fromReverseList $2+ in CommonGroup () (getTransSpan $1 alist) (Just $1) alist }+| '/' '/' UNINITIALIZED_DECLARATOR_LIST+ { let alist = fromReverseList $3+ in CommonGroup () (getTransSpan $1 alist) Nothing alist }++INIT_COMMON_GROUP :: { CommonGroup A0 }+: COMMON_NAME UNINITIALIZED_DECLARATOR_LIST+ { let alist = fromReverseList $2+ in CommonGroup () (getTransSpan $1 alist) (Just $1) alist }+| '/' '/' UNINITIALIZED_DECLARATOR_LIST+ { let alist = fromReverseList $3+ in CommonGroup () (getTransSpan $1 alist) Nothing alist }+| UNINITIALIZED_DECLARATOR_LIST+ { let alist = fromReverseList $1+ in CommonGroup () (getSpan alist) Nothing alist }++EQUIVALENCE_GROUPS :: { [ AList Expression A0 ] }+: EQUIVALENCE_GROUPS ',' '(' PART_REFS ')'+ { setSpan (getTransSpan $3 $5) (fromReverseList $4) : $1 }+| '(' PART_REFS ')'+ { [ setSpan (getTransSpan $1 $3) (fromReverseList $2) ] }++NAMELISTS :: { [ Namelist A0 ] }+: NAMELISTS NAMELIST { $2 : $1 }+| NAMELISTS ',2' NAMELIST { $3 : $1 }+| NAMELIST { [ $1 ] }++NAMELIST :: { Namelist A0 }+: '/' VARIABLE '/' VARIABLES+ { Namelist () (getTransSpan $1 $4) $2 $ fromReverseList $4 }++MAYBE_VARIABLES :: { Maybe (AList Expression A0) }+: VARIABLES { Just $ fromReverseList $1 } | {- EMPTY -} { Nothing }++VARIABLES :: { [ Expression A0 ] }+: VARIABLES ',' VARIABLE { $3 : $1 }+| VARIABLE { [ $1 ] }++IMP_LISTS :: { [ ImpList A0 ] }+: IMP_LISTS ',' IMP_LIST { $3 : $1 }+| IMP_LIST { [ $1 ] }++IMP_LIST :: { ImpList A0 }+: TYPE_SPEC '(2' IMP_ELEMENTS ')'+ { ImpList () (getTransSpan $1 $4) $1 (aReverse $3) }++IMP_ELEMENTS :: { AList ImpElement A0 }+: IMP_ELEMENTS ',' IMP_ELEMENT { setSpan (getTransSpan $1 $3) $ $3 `aCons` $1 }+| IMP_ELEMENT { AList () (getSpan $1) [ $1 ] }++IMP_ELEMENT :: { ImpElement A0 }+: id {% do+ let (TId s id) = $1+ if length id /= 1+ then fail "Implicit argument must be a character."+ else return $ ImpCharacter () s id+ }+| id '-' id {% do+ let (TId _ id1) = $1+ let (TId _ id2) = $3+ if length id1 /= 1 || length id2 /= 1+ then fail "Implicit argument must be a character."+ else return $ ImpRange () (getTransSpan $1 $3) id1 id2+ }++PARAMETER_ASSIGNMENTS :: { [ Declarator A0 ] }+: PARAMETER_ASSIGNMENTS ',' PARAMETER_ASSIGNMENT { $3 : $1 }+| PARAMETER_ASSIGNMENT { [ $1 ] }++PARAMETER_ASSIGNMENT :: { Declarator A0 }+: VARIABLE '=' EXPRESSION+ { Declarator () (getTransSpan $1 $3) $1 ScalarDecl Nothing (Just $3) }++DECLARATION_STATEMENT :: { Statement A0 }+: TYPE_SPEC ATTRIBUTE_LIST '::' INITIALIZED_DECLARATOR_LIST+ { let { mAttrAList = if null $2 then Nothing else Just $ fromReverseList $2;+ declAList = fromReverseList $4 }+ in StDeclaration () (getTransSpan $1 declAList) $1 mAttrAList declAList }+| TYPE_SPEC INITIALIZED_DECLARATOR_LIST+ { let { declAList = fromReverseList $2 }+ in StDeclaration () (getTransSpan $1 declAList) $1 Nothing declAList }++ATTRIBUTE_LIST :: { [ Attribute A0 ] }+: ATTRIBUTE_LIST ',' ATTRIBUTE_SPEC { $3 : $1 }+| {- EMPTY -} { [ ] }++ATTRIBUTE_SPEC :: { Attribute A0 }+: public { AttrPublic () (getSpan $1) }+| private { AttrPrivate () (getSpan $1) }+| protected { AttrProtected () (getSpan $1) }+| allocatable { AttrAllocatable () (getSpan $1) }+| asynchronous { AttrAsynchronous () (getSpan $1) }+| dimension '(' DIMENSION_DECLARATORS ')'+ { AttrDimension () (getTransSpan $1 $4) (aReverse $3) }+| external { AttrExternal () (getSpan $1) }+| intent '(' INTENT_CHOICE ')' { AttrIntent () (getTransSpan $1 $4) $3 }+| intrinsic { AttrIntrinsic () (getSpan $1) }+| optional { AttrOptional () (getSpan $1) }+| pointer { AttrPointer () (getSpan $1) }+| parameter { AttrParameter () (getSpan $1) }+| save { AttrSave () (getSpan $1) }+| target { AttrTarget () (getSpan $1) }+| value { AttrValue () (getSpan $1) }+| volatile { AttrVolatile () (getSpan $1) }+| SUFFIX { AttrSuffix () (getSpan $1) $1 }++INTENT_CHOICE :: { Intent } : in { In } | out { Out } | inout { InOut }++DATA_GROUPS :: { [ DataGroup A0 ] }+: DATA_GROUPS MAYBE_COMMA DATA_LIST slash EXPRESSION_LIST slash+ { let { nameAList = fromReverseList $3;+ dataAList = fromReverseList $5 }+ in DataGroup () (getTransSpan nameAList $6) nameAList dataAList : $1 }+| DATA_LIST slash EXPRESSION_LIST slash+ { let { nameAList = fromReverseList $1;+ dataAList = fromReverseList $3 }+ in [ DataGroup () (getTransSpan nameAList $4) nameAList dataAList ] }++MAYBE_COMMA :: { () } : ',' { () } | {- EMPTY -} { () }++DATA_LIST :: { [ Expression A0 ] }+: DATA_LIST ',' DATA_ELEMENT { $3 : $1 }+| DATA_ELEMENT { [ $1 ] }++DATA_ELEMENT :: { Expression A0 }+: DATA_REF { $1 } | IMPLIED_DO { $1 }++SAVE_ARGS :: { [ Expression A0 ] }+: SAVE_ARGS ',' SAVE_ARG { $3 : $1 } | SAVE_ARG { [ $1 ] }++SAVE_ARG :: { Expression A0 } : COMMON_NAME { $1 } | VARIABLE { $1 }++COMMON_NAME :: { Expression A0 }+: '/' VARIABLE '/' { setSpan (getTransSpan $1 $3) $2 }++INITIALIZED_DECLARATOR_LIST :: { [ Declarator A0 ] }+: INITIALIZED_DECLARATOR_LIST ',' INITIALIZED_DECLARATOR { $3 : $1 }+| INITIALIZED_DECLARATOR { [ $1 ] }++UNINITIALIZED_DECLARATOR_LIST :: { [ Declarator A0 ] }+: UNINITIALIZED_DECLARATOR_LIST ',' DECLARATOR { $3 : $1 }+| DECLARATOR { [ $1 ] }++INITIALIZED_DECLARATOR :: { Declarator A0 }+: DECLARATOR '=' EXPRESSION { setInitialisation $1 $3 }+| DECLARATOR '=>' EXPRESSION { setInitialisation $1 $3 }+| DECLARATOR { $1 }++DECLARATOR :: { Declarator A0 }+: VARIABLE+ { Declarator () (getSpan $1) $1 ScalarDecl Nothing Nothing }+| VARIABLE '*' EXPRESSION+ { Declarator () (getTransSpan $1 $3) $1 ScalarDecl (Just $3) Nothing }+| VARIABLE '*' '(' '*' ')'+ { let star = ExpValue () (getSpan $4) ValStar+ in Declarator () (getTransSpan $1 $5) $1 ScalarDecl (Just star) Nothing }+| VARIABLE '(' DIMENSION_DECLARATORS ')'+ { Declarator () (getTransSpan $1 $4) $1 (ArrayDecl (aReverse $3)) Nothing Nothing }+| VARIABLE '(' DIMENSION_DECLARATORS ')' '*' EXPRESSION+ { Declarator () (getTransSpan $1 $6) $1 (ArrayDecl (aReverse $3)) (Just $6) Nothing }+-- nonstandard char array syntax (wrong order for dimensions & charlen)+| VARIABLE '*' EXPRESSION '(' DIMENSION_DECLARATORS ')'+ { Declarator () (getTransSpan $1 $6) $1 (ArrayDecl (aReverse $5)) (Just $3) Nothing }+| VARIABLE '(' DIMENSION_DECLARATORS ')' '*' '(' '*' ')'+ { let star = ExpValue () (getSpan $7) ValStar+ in Declarator () (getTransSpan $1 $8) $1 (ArrayDecl (aReverse $3)) (Just star) Nothing }++DIMENSION_DECLARATORS :: { AList DimensionDeclarator A0 }+: DIMENSION_DECLARATORS ',' DIMENSION_DECLARATOR+ { setSpan (getTransSpan $1 $3) $ $3 `aCons` $1 }+| DIMENSION_DECLARATOR+ { AList () (getSpan $1) [ $1 ] }++DIMENSION_DECLARATOR :: { DimensionDeclarator A0 }+: EXPRESSION ':' EXPRESSION+ { DimensionDeclarator () (getTransSpan $1 $3) (Just $1) (Just $3) }+| EXPRESSION { DimensionDeclarator () (getSpan $1) Nothing (Just $1) }+-- Lower bound only+| EXPRESSION ':'+ { DimensionDeclarator () (getTransSpan $1 $2) (Just $1) Nothing }+| EXPRESSION ':' '*'+ { let { span = getSpan $3;+ star = ExpValue () span ValStar }+ in DimensionDeclarator () (getTransSpan $1 span) (Just $1) (Just star) }+| '*'+ { let { span = getSpan $1;+ star = ExpValue () span ValStar }+ in DimensionDeclarator () span Nothing (Just star) }+| ':'+ { let span = getSpan $1+ in DimensionDeclarator () span Nothing Nothing }++MAYBE_TYPE_SPEC :: { Maybe (TypeSpec A0) }+: TYPE_SPEC '::' { Just $1 }+| {- empty -} { Nothing }++TYPE_SPEC :: { TypeSpec A0 }+: integer KIND_SELECTOR { TypeSpec () (getSpan ($1, $2)) TypeInteger $2 }+| real KIND_SELECTOR { TypeSpec () (getSpan ($1, $2)) TypeReal $2 }+| doublePrecision { TypeSpec () (getSpan $1) TypeDoublePrecision Nothing }+| complex KIND_SELECTOR { TypeSpec () (getSpan ($1, $2)) TypeComplex $2 }+| character CHAR_SELECTOR { TypeSpec () (getSpan ($1, $2)) TypeCharacter $2 }+| logical KIND_SELECTOR { TypeSpec () (getSpan ($1, $2)) TypeLogical $2 }+| type '(' id ')'+ { let TId _ id = $3+ in TypeSpec () (getTransSpan $1 $4) (TypeCustom id) Nothing }+-- R502+| class '(' '*' ')' { TypeSpec () (getSpan ($1, $4)) ClassStar Nothing }+-- FIXME: this (and TypeCustom) can accept parameterised types. See type-param-value.+-- Needs refactoring as this is used in various parts of the spec to consolidate+-- uses of ':', '*' and scalar-int-exp.+| class '(' id ')'+ { let TId _ id = $3+ in TypeSpec () (getSpan ($1, $4)) (ClassCustom id) Nothing }++KIND_SELECTOR :: { Maybe (Selector A0) }+: '(' EXPRESSION ')'+ { Just $ Selector () (getTransSpan $1 $3) Nothing (Just $2) }+| '(' kind '=' EXPRESSION ')'+ { Just $ Selector () (getTransSpan $1 $5) Nothing (Just $4) }+| '*' EXPRESSION -- non-standard but commonly used extension+ { Just $ Selector () (getTransSpan $1 $2) Nothing (Just $2) }+| {- EMPTY -} { Nothing }++CHAR_SELECTOR :: { Maybe (Selector A0) }+: '*' EXPRESSION+ { Just $ Selector () (getTransSpan $1 $2) (Just $2) Nothing }+-- The following rule is a bug in the spec.+-- | '*' EXPRESSION ','+-- { Just $ Selector () (getTransSpan $1 $2) (Just $2) Nothing }+| '*' '(' '*' ')'+ { let star = ExpValue () (getSpan $3) ValStar+ in Just $ Selector () (getTransSpan $1 $4) (Just star) Nothing }+| '(' LEN_EXPRESSION ')'+ { Just $ Selector () (getTransSpan $1 $3) (Just $2) Nothing }+| '(' len '=' LEN_EXPRESSION ')'+ { Just $ Selector () (getTransSpan $1 $5) (Just $4) Nothing }+| '(' kind '=' EXPRESSION ')'+ { Just $ Selector () (getTransSpan $1 $5) Nothing (Just $4) }+| '(' LEN_EXPRESSION ',' EXPRESSION ')'+ { Just $ Selector () (getTransSpan $1 $5) (Just $2) (Just $4) }+| '(' LEN_EXPRESSION ',' kind '=' EXPRESSION ')'+ { Just $ Selector () (getTransSpan $1 $7) (Just $2) (Just $6) }+| '(' len '=' LEN_EXPRESSION ',' kind '=' EXPRESSION ')'+ { Just $ Selector () (getTransSpan $1 $9) (Just $4) (Just $8) }+| '(' kind '=' EXPRESSION ',' len '=' LEN_EXPRESSION ')'+ { Just $ Selector () (getTransSpan $1 $9) (Just $8) (Just $4) }+| {- EMPTY -} { Nothing }++{- R402 -}+LEN_EXPRESSION :: { Expression A0 }+: EXPRESSION { $1 }+| '*' { ExpValue () (getSpan $1) ValStar }+| ':' { ExpValue () (getSpan $1) ValColon }++EXPRESSION :: { Expression A0 }+: EXPRESSION '+' EXPRESSION+ { ExpBinary () (getTransSpan $1 $3) Addition $1 $3 }+| EXPRESSION '-' EXPRESSION+ { ExpBinary () (getTransSpan $1 $3) Subtraction $1 $3 }+| EXPRESSION '*' EXPRESSION+ { ExpBinary () (getTransSpan $1 $3) Multiplication $1 $3 }+| EXPRESSION '/' EXPRESSION+ { ExpBinary () (getTransSpan $1 $3) Division $1 $3 }+| EXPRESSION '**' EXPRESSION+ { ExpBinary () (getTransSpan $1 $3) Exponentiation $1 $3 }+| EXPRESSION '/' '/' EXPRESSION %prec CONCAT+ { ExpBinary () (getTransSpan $1 $4) Concatenation $1 $4 }+| ARITHMETIC_SIGN EXPRESSION %prec SIGN+ { ExpUnary () (getTransSpan (fst $1) $2) (snd $1) $2 }+| EXPRESSION or EXPRESSION+ { ExpBinary () (getTransSpan $1 $3) Or $1 $3 }+| EXPRESSION and EXPRESSION+ { ExpBinary () (getTransSpan $1 $3) And $1 $3 }+| not EXPRESSION+ { ExpUnary () (getTransSpan $1 $2) Not $2 }+| EXPRESSION eqv EXPRESSION+ { ExpBinary () (getTransSpan $1 $3) Equivalent $1 $3 }+| EXPRESSION neqv EXPRESSION+ { ExpBinary () (getTransSpan $1 $3) NotEquivalent $1 $3 }+| EXPRESSION RELATIONAL_OPERATOR EXPRESSION %prec RELATIONAL+ { ExpBinary () (getTransSpan $1 $3) $2 $1 $3 }+| opCustom EXPRESSION %prec DEFINED_UNARY+ { let TOpCustom span str = $1+ in ExpUnary () (getTransSpan span $2) (UnCustom str) $2 }+| EXPRESSION opCustom EXPRESSION+ { let TOpCustom _ str = $2+ in ExpBinary () (getTransSpan $1 $3) (BinCustom str) $1 $3 }+| '(' EXPRESSION ')' { setSpan (getTransSpan $1 $3) $2 }+| NUMERIC_LITERAL { $1 }+| '(' EXPRESSION ',' EXPRESSION ')'+ { ExpValue () (getTransSpan $1 $5) (ValComplex $2 $4) }+| LOGICAL_LITERAL { $1 }+| STRING { $1 }+| DATA_REF { $1 }+| IMPLIED_DO { $1 }+| '(/' EXPRESSION_LIST '/)'+ { ExpInitialisation () (getTransSpan $1 $3) (fromReverseList $2) }+| operator '(' opCustom ')'+ { let TOpCustom _ op = $3+ in ExpValue () (getTransSpan $1 $4) (ValOperator op) }+| assignment { ExpValue () (getSpan $1) ValAssignment }+| '*' INTEGER_LITERAL { ExpReturnSpec () (getTransSpan $1 $2) $2 }++DATA_REFS :: { [ Expression A0 ] }+: DATA_REFS ',' DATA_REF { $3 : $1 }+| DATA_REF { [ $1 ] }++DATA_REF :: { Expression A0 }+: DATA_REF '%' PART_REF { ExpDataRef () (getTransSpan $1 $3) $1 $3 }+| PART_REF { $1 }++PART_REFS :: { [ Expression A0 ] }+: PART_REFS ',' PART_REF { $3 : $1 }+| PART_REF { [ $1 ] }++PART_REF :: { Expression A0 }+: VARIABLE { $1 }+| VARIABLE '(' ')'+ { ExpFunctionCall () (getTransSpan $1 $3) $1 Nothing }+| VARIABLE '(' INDICIES ')'+ { ExpSubscript () (getTransSpan $1 $4) $1 (fromReverseList $3) }+| VARIABLE '(' INDICIES ')' '(' INDICIES ')'+ { let innerSub = ExpSubscript () (getTransSpan $1 $4) $1 (fromReverseList $3)+ in ExpSubscript () (getTransSpan $1 $7) innerSub (fromReverseList $6) }++INDICIES :: { [ Index A0 ] }+: INDICIES ',' INDEX { $3 : $1 }+| INDEX { [ $1 ] }++INDEX :: { Index A0 }+: RANGE { $1 }+| RANGE ':' EXPRESSION+ { let IxRange () s lower upper _ = $1+ in IxRange () (getTransSpan s $3) lower upper (Just $3) }+| EXPRESSION { IxSingle () (getSpan $1) Nothing $1 }+-- Following is only as an intermediate stage before having been turned into+-- an argument by later transformation.+| id '=' EXPRESSION+ { let TId s id = $1 in IxSingle () (getTransSpan $1 s) (Just id) $3 }++RANGE :: { Index A0 }+: ':' { IxRange () (getSpan $1) Nothing Nothing Nothing }+| ':' EXPRESSION { IxRange () (getTransSpan $1 $2) Nothing (Just $2) Nothing }+| EXPRESSION ':' { IxRange () (getTransSpan $1 $2) (Just $1) Nothing Nothing }+| EXPRESSION ':' EXPRESSION+ { IxRange () (getTransSpan $1 $3) (Just $1) (Just $3) Nothing }++DO_SPECIFICATION :: { DoSpecification A0 }+: EXPRESSION_ASSIGNMENT_STATEMENT ',' EXPRESSION ',' EXPRESSION+ { DoSpecification () (getTransSpan $1 $5) $1 $3 (Just $5) }+| EXPRESSION_ASSIGNMENT_STATEMENT ',' EXPRESSION+ { DoSpecification () (getTransSpan $1 $3) $1 $3 Nothing }++IMPLIED_DO :: { Expression A0 }+: '(' EXPRESSION ',' DO_SPECIFICATION ')'+ { let expList = AList () (getSpan $2) [ $2 ]+ in ExpImpliedDo () (getTransSpan $1 $5) expList $4 }+| '(' EXPRESSION ',' EXPRESSION ',' DO_SPECIFICATION ')'+ { let expList = AList () (getTransSpan $2 $4) [ $2, $4 ]+ in ExpImpliedDo () (getTransSpan $1 $5) expList $6 }+| '(' EXPRESSION ',' EXPRESSION ',' EXPRESSION_LIST ',' DO_SPECIFICATION ')'+ { let { exps = reverse $6;+ expList = AList () (getTransSpan $2 exps) ($2 : $4 : reverse $6) }+ in ExpImpliedDo () (getTransSpan $1 $9) expList $8 }++FORALL :: { Statement A0 }+: id ':' forall FORALL_HEADER {+ let (TId s1 id) = $1 in+ let (h,s2) = $4 in+ StForall () (getTransSpan s1 s2) (Just id) h+}+| forall FORALL_HEADER {+ let (h,s) = $2 in+ StForall () (getTransSpan $1 s) Nothing h+}+| forall FORALL_HEADER FORALL_ASSIGNMENT_STMT {+ let (h,_) = $2 in+ StForallStatement () (getTransSpan $1 $3) h $3+}++FORALL_HEADER :: { (ForallHeader A0, SrcSpan) }+-- Standard simple forall header+: '(' FORALL_TRIPLET_SPEC ')' { (ForallHeader [$2] Nothing, getTransSpan $1 $3) }+-- forall header with scale expression+| '(' '(' FORALL_TRIPLET_SPEC ')' ',' EXPRESSION ')'+ { (ForallHeader [$3] (Just $6), getTransSpan $1 $7) }+-- multi forall header+| '(' FORALL_TRIPLET_SPEC_LIST_PLUS_STRIDE ')'+ { (ForallHeader $2 Nothing, getTransSpan $1 $3) }+-- multi forall header with scale+| '(' FORALL_TRIPLET_SPEC_LIST_PLUS_STRIDE ',' EXPRESSION ')'+ { (ForallHeader $2 (Just $4), getTransSpan $1 $5) }++FORALL_TRIPLET_SPEC_LIST_PLUS_STRIDE+ :: { [(Name, Expression A0, Expression A0, Maybe (Expression A0))] }+: '(' FORALL_TRIPLET_SPEC ')' ',' FORALL_TRIPLET_SPEC_LIST_PLUS_STRIDE { $2 : $5 }+| {- empty -} { [] }++FORALL_TRIPLET_SPEC :: { (Name, Expression A0, Expression A0, Maybe (Expression A0)) }+: NAME '=' EXPRESSION ':' EXPRESSION { ($1, $3, $5, Nothing) }+| NAME '=' EXPRESSION ':' EXPRESSION ',' EXPRESSION { ($1, $3, $5, Just $7) }++FORALL_ASSIGNMENT_STMT :: { Statement A0 }+: EXPRESSION_ASSIGNMENT_STATEMENT { $1 }+| POINTER_ASSIGNMENT_STMT { $1 }++POINTER_ASSIGNMENT_STMT :: { Statement A0 }+: DATA_REF '=>' EXPRESSION { StPointerAssign () (getTransSpan $1 $3) $1 $3 }++END_FORALL :: { Statement A0 }+: endforall { StEndForall () (getSpan $1) Nothing }+| endforall id { let (TId s id) = $2 in StEndForall () (getTransSpan $1 s) (Just id)}++EXPRESSION_LIST :: { [ Expression A0 ] }+: EXPRESSION_LIST ',' EXPRESSION { $3 : $1 }+| EXPRESSION { [ $1 ] }++ARITHMETIC_SIGN :: { (SrcSpan, UnaryOp) }+: '-' { (getSpan $1, Minus) }+| '+' { (getSpan $1, Plus) }++RELATIONAL_OPERATOR :: { BinaryOp }+: '==' { EQ }+| '!=' { NE }+| '>' { GT }+| '>=' { GTE }+| '<' { LT }+| '<=' { LTE }++VARIABLE :: { Expression A0 }+: id { ExpValue () (getSpan $1) $ let (TId _ s) = $1 in ValVariable s }++NUMERIC_LITERAL :: { Expression A0 }+: INTEGER_LITERAL { $1 } | REAL_LITERAL { $1 }++INTEGERS :: { [ Expression A0 ] }+: INTEGERS ',' INTEGER_LITERAL { $3 : $1 }+| INTEGER_LITERAL { [ $1 ] }++INTEGER_LITERAL :: { Expression A0 }+: int+ { let TIntegerLiteral s i = $1+ in ExpValue () s $ ValInteger i Nothing }+| int '_' KIND_PARAM+ { let TIntegerLiteral s i = $1+ in ExpValue () s $ ValInteger i (Just $3) }+| boz { let TBozLiteral s b = $1 in ExpValue () s $ ValBoz b }++REAL_LITERAL :: { Expression A0 }+: float+ { let TRealLiteral s r = $1+ in ExpValue () s $ ValReal r Nothing }+| float '_' KIND_PARAM+ { let TRealLiteral s r = $1+ in ExpValue () s $ ValReal r (Just $3) }++LOGICAL_LITERAL :: { Expression A0 }+: bool+ { let TLogicalLiteral s b = $1+ in ExpValue () s (ValLogical b Nothing) }+| bool '_' KIND_PARAM+ { let TLogicalLiteral s b = $1+ in ExpValue () s (ValLogical b (Just $3)) }++KIND_PARAM :: { Expression A0 }+: INTEGER_LITERAL { $1 }+| VARIABLE { $1 }++STRING :: { Expression A0 }+: string { let TString s c = $1 in ExpValue () s $ ValString c }++cDATA :: { () } : {% pushContext ConData }+cIMPLICIT :: { () } : {% pushContext ConImplicit }+cNAMELIST :: { () } : {% pushContext ConNamelist }+cCOMMON :: { () } : {% pushContext ConCommon }+cPOP :: { () } : {% popContext }
+ src/Language/Fortran/Parser/Free/Fortran90.y view
@@ -0,0 +1,1161 @@+-- -*- Mode: Haskell -*-+-- vim: ft=haskell+{+module Language.Fortran.Parser.Free.Fortran90+ ( programParser+ , functionParser+ , blockParser+ , statementParser+ , expressionParser+ ) where++import Language.Fortran.Version+import Language.Fortran.Util.Position+import Language.Fortran.Parser.Monad+import Language.Fortran.Parser.Free.Lexer+import Language.Fortran.Parser.Free.Utils+import Language.Fortran.AST++import Prelude hiding ( EQ, LT, GT ) -- Same constructors exist in the AST+import Data.Either ( partitionEithers )++}++%name programParser PROGRAM+%name functionParser SUBPROGRAM_UNIT+%name blockParser BLOCK+%name statementParser STATEMENT+%name expressionParser EXPRESSION+%monad { LexAction }+%lexer { lexer } { TEOF _ }+%tokentype { Token }+%error { parseError }++%token+ id { TId _ _ }+ comment { TComment _ _ }+ string { TString _ _ }+ int { TIntegerLiteral _ _ }+ float { TRealLiteral _ _ }+ boz { TBozLiteral _ _ }+ '_' { TUnderscore _ }+ ',' { TComma _ }+ ',2' { TComma2 _ }+ ';' { TSemiColon _ }+ ':' { TColon _ }+ '::' { TDoubleColon _ }+ '=' { TOpAssign _ }+ '=>' { TArrow _ }+ '%' { TPercent _ }+ '(' { TLeftPar _ }+ '(2' { TLeftPar2 _ }+ ')' { TRightPar _ }+ '(/' { TLeftInitPar _ }+ '/)' { TRightInitPar _ }+ opCustom { TOpCustom _ _ }+ '**' { TOpExp _ }+ '+' { TOpPlus _ }+ '-' { TOpMinus _ }+ '*' { TStar _ }+ '/' { TOpDivision _ }+ slash { TSlash _ }+ or { TOpOr _ }+ and { TOpAnd _ }+ not { TOpNot _ }+ eqv { TOpEquivalent _ }+ neqv { TOpNotEquivalent _ }+ '<' { TOpLT _ }+ '<=' { TOpLE _ }+ '==' { TOpEQ _ }+ '!=' { TOpNE _ }+ '>' { TOpGT _ }+ '>=' { TOpGE _ }+ bool { TLogicalLiteral _ _ }+ program { TProgram _ }+ endProgram { TEndProgram _ }+ function { TFunction _ }+ endFunction { TEndFunction _ }+ result { TResult _ }+ recursive { TRecursive _ }+ subroutine { TSubroutine _ }+ endSubroutine { TEndSubroutine _ }+ blockData { TBlockData _ }+ endBlockData { TEndBlockData _ }+ module { TModule _ }+ endModule { TEndModule _ }+ contains { TContains _ }+ use { TUse _ }+ only { TOnly _ }+ interface { TInterface _ }+ endInterface { TEndInterface _ }+ moduleProcedure { TModuleProcedure _ }+ assignment { TAssignment _ }+ operator { TOperator _ }+ call { TCall _ }+ return { TReturn _ }+ entry { TEntry _ }+ include { TInclude _ }+ public { TPublic _ }+ private { TPrivate _ }+ parameter { TParameter _ }+ allocatable { TAllocatable _ }+ dimension { TDimension _ }+ external { TExternal _ }+ intent { TIntent _ }+ intrinsic { TIntrinsic _ }+ optional { TOptional _ }+ pointer { TPointer _ }+ save { TSave _ }+ target { TTarget _ }+ in { TIn _ }+ out { TOut _ }+ inout { TInOut _ }+ data { TData _ }+ namelist { TNamelist _ }+ implicit { TImplicit _ }+ equivalence { TEquivalence _ }+ common { TCommon _ }+ allocate { TAllocate _ }+ stat { TStat _ }+ deallocate { TDeallocate _ }+ nullify { TNullify _ }+ none { TNone _ }+ goto { TGoto _ }+ assign { TAssign _ }+ to { TTo _ }+ continue { TContinue _ }+ stop { TStop _ }+ pause { TPause _ }+ do { TDo _ }+ enddo { TEndDo _ }+ while { TWhile _ }+ if { TIf _ }+ then { TThen _ }+ else { TElse _ }+ elsif { TElsif _ }+ endif { TEndIf _ }+ case { TCase _ }+ selectcase { TSelectCase _ }+ endselect { TEndSelect _ }+ default { TDefault _ }+ cycle { TCycle _ }+ exit { TExit _ }+ where { TWhere _ }+ elsewhere { TElsewhere _ }+ endwhere { TEndWhere _ }+ type { TType _ }+ endType { TEndType _ }+ sequence { TSequence _ }+ kind { TKind _ }+ len { TLen _ }+ integer { TInteger _ }+ real { TReal _ }+ doublePrecision { TDoublePrecision _ }+ logical { TLogical _ }+ character { TCharacter _ }+ complex { TComplex _ }+ open { TOpen _ }+ close { TClose _ }+ read { TRead _ }+ write { TWrite _ }+ print { TPrint _ }+ backspace { TBackspace _ }+ rewind { TRewind _ }+ inquire { TInquire _ }+ endfile { TEndfile _ }+ format { TFormat _ }+ blob { TBlob _ _ }+ end { TEnd _ }+ newline { TNewline _ }++-- Precedence of operators++-- Level 6+%left opCustom++-- Level 5+%left eqv neqv+%left or+%left and+%right not++-- Level 4+%nonassoc '==' '!=' '>' '<' '>=' '<='+%nonassoc RELATIONAL++-- Level 3+%left CONCAT++-- Level 2+%left '+' '-'+%left '*' '/'+%right SIGN+%right '**'++-- Level 1+%right DEFINED_UNARY++-- Level 0+%left '%'++%%++maybe(p)+: p { Just $1 }+| {- empty -} { Nothing }++-- This rule is to ignore leading whitespace+PROGRAM :: { ProgramFile A0 }+: NEWLINE PROGRAM_INNER { $2 }+| PROGRAM_INNER { $1 }++PROGRAM_INNER :: { ProgramFile A0 }+: PROGRAM_UNITS { ProgramFile (MetaInfo { miVersion = Fortran90, miFilename = "" }) (reverse $1) }+| {- empty -} { ProgramFile (MetaInfo { miVersion = Fortran90, miFilename = "" }) [] }++PROGRAM_UNITS :: { [ ProgramUnit A0 ] }+: PROGRAM_UNITS PROGRAM_UNIT MAYBE_NEWLINE { $2 : $1 }+| PROGRAM_UNIT MAYBE_NEWLINE { [ $1 ] }++PROGRAM_UNIT :: { ProgramUnit A0 }+: program NAME NEWLINE BLOCKS MAYBE_SUBPROGRAM_UNITS PROGRAM_END+ {% do { unitNameCheck $6 $2;+ return $ PUMain () (getTransSpan $1 $6) (Just $2) (reverse $4) $5 } }+| module NAME NEWLINE BLOCKS MAYBE_SUBPROGRAM_UNITS MODULE_END+ {% do { unitNameCheck $6 $2;+ return $ PUModule () (getTransSpan $1 $6) $2 (reverse $4) $5 } }+| blockData NEWLINE BLOCKS BLOCK_DATA_END+ { PUBlockData () (getTransSpan $1 $4) Nothing (reverse $3) }+| blockData NAME NEWLINE BLOCKS BLOCK_DATA_END+ {% do { unitNameCheck $5 $2;+ return $ PUBlockData () (getTransSpan $1 $5) (Just $2) (reverse $4) } }+| SUBPROGRAM_UNIT { $1 }++MAYBE_SUBPROGRAM_UNITS :: { Maybe [ ProgramUnit A0 ] }+: contains NEWLINE SUBPROGRAM_UNITS { Just $ reverse $3 }+| {- Empty -} { Nothing }++SUBPROGRAM_UNITS :: { [ ProgramUnit A0 ] }+: SUBPROGRAM_UNITS SUBPROGRAM_UNIT NEWLINE { $2 : $1 }+| {- EMPTY -} { [ ] }++SUBPROGRAM_UNIT :: { ProgramUnit A0 }+: PREFIXES function NAME MAYBE_ARGUMENTS MAYBE_RESULT MAYBE_COMMENT NEWLINE BLOCKS MAYBE_SUBPROGRAM_UNITS FUNCTION_END+ {% do { unitNameCheck $10 $3;+ let (pfxs, typeSpec) = case partitionEithers $1 of+ { (ps, t:_) -> (fromReverseList' ps, Just t)+ ; (ps, []) -> (fromReverseList' ps, Nothing) } in+ let sfx = emptySuffixes in+ let ss = if null $1 then getTransSpan $2 $10 else getTransSpan (reverse $1) $10 in+ return $ PUFunction () ss typeSpec (pfxs, sfx) $3 $4 $5 (reverse $8) $9 } }+| PREFIXES subroutine NAME MAYBE_ARGUMENTS MAYBE_COMMENT NEWLINE BLOCKS MAYBE_SUBPROGRAM_UNITS SUBROUTINE_END+ {% do { unitNameCheck $9 $3;+ (pfxs, typeSpec) <- case partitionEithers $1 of+ { (ps, t:_) -> fail "Subroutines cannot have return types."+ ; (ps, []) -> return (fromReverseList' ps, Nothing) };+ let sfx = emptySuffixes in+ let ss = if null $1 then getTransSpan $2 $9 else getTransSpan (reverse $1) $9 in+ return $ PUSubroutine () ss (pfxs, sfx) $3 $4 (reverse $7) $8 } }+| comment { let (TComment s c) = $1 in PUComment () s (Comment c) }++-- (Fortran2003) R1227, Fortran95/90 (...)+PREFIXES :: { [Either (Prefix A0) (TypeSpec A0)] }+: PREFIXES PREFIX { $2:$1 }+| {- EMPTY -} { [] }++-- (Fortran2003) R1228, Fortran95/90 (...)+PREFIX :: { Either (Prefix A0) (TypeSpec A0) }+: recursive { Left $ PfxRecursive () (getSpan $1) }+| TYPE_SPEC { Right $1 }++RESULT :: { Expression A0 }+: result '(' VARIABLE ')' { $3 }++MAYBE_RESULT :: { Maybe (Expression A0) }+: RESULT { Just $1 }+| {- empty -} { Nothing }++MAYBE_ARGUMENTS :: { Maybe (AList Expression A0) }+: '(' MAYBE_VARIABLES ')' { $2 }+| {- Nothing -} { Nothing }++PROGRAM_END :: { Token }+: end { $1 } | endProgram { $1 } | endProgram id { $2 }+MODULE_END :: { Token }+: end { $1 } | endModule { $1 } | endModule id { $2 }+FUNCTION_END :: { Token }+: end { $1 } | endFunction { $1 } | endFunction id { $2 }+SUBROUTINE_END :: { Token }+: end { $1 } | endSubroutine { $1 } | endSubroutine id { $2 }+BLOCK_DATA_END :: { Token }+: end { $1 } | endBlockData { $1 } | endBlockData id { $2 }+INTERFACE_END :: { Token }+: end { $1 } | endInterface { $1 } | endInterface id { $2 }++NAME :: { Name } : id { let (TId _ name) = $1 in name }++BLOCKS :: { [ Block A0 ] } : BLOCKS BLOCK { $2 : $1 } | {- EMPTY -} { [ ] }++BLOCK :: { Block A0 }+: IF_BLOCK MAYBE_COMMENT NEWLINE { $1 }+| CASE_BLOCK MAYBE_COMMENT NEWLINE { $1 }+| INTEGER_LITERAL STATEMENT MAYBE_COMMENT NEWLINE+ { BlStatement () (getTransSpan $1 $2) (Just $1) $2 }+| STATEMENT MAYBE_COMMENT NEWLINE { BlStatement () (getSpan $1) Nothing $1 }+| interface MAYBE_EXPRESSION MAYBE_COMMENT NEWLINE SUBPROGRAM_UNITS2 MODULE_PROCEDURES INTERFACE_END MAYBE_COMMENT NEWLINE+ { BlInterface () (getTransSpan $1 $9) $2 False (reverse $5) (reverse $6) }+| interface MAYBE_EXPRESSION MAYBE_COMMENT NEWLINE MODULE_PROCEDURES INTERFACE_END MAYBE_COMMENT NEWLINE+ { BlInterface () (getTransSpan $1 $8) $2 False [ ] (reverse $5) }+| COMMENT_BLOCK { $1 }++IF_BLOCK :: { Block A0 }+: if '(' EXPRESSION ')' then MAYBE_COMMENT NEWLINE BLOCKS ELSE_BLOCKS+ { let { startSpan = getSpan $1;+ (endSpan, conds, blocks, endLabel) = $9;+ span = getTransSpan startSpan endSpan }+ in BlIf () span Nothing Nothing ((Just $3):conds) ((reverse $8):blocks) endLabel }+| id ':' if '(' EXPRESSION ')' then MAYBE_COMMENT NEWLINE BLOCKS ELSE_BLOCKS+ { let { TId startSpan startName = $1;+ (endSpan, conds, blocks, endLabel) = $11;+ span = getTransSpan startSpan endSpan }+ in BlIf () span Nothing (Just startName) ((Just $5):conds) ((reverse $10):blocks) endLabel }+| INTEGER_LITERAL if '(' EXPRESSION ')' then MAYBE_COMMENT NEWLINE BLOCKS ELSE_BLOCKS+ { let { startSpan = getSpan $1;+ startLabel = Just $1;+ (endSpan, conds, blocks, endLabel) = $10;+ span = getTransSpan startSpan endSpan }+ in BlIf () span startLabel Nothing ((Just $4):conds) ((reverse $9):blocks) endLabel }+| INTEGER_LITERAL id ':' if '(' EXPRESSION ')' then MAYBE_COMMENT NEWLINE BLOCKS ELSE_BLOCKS+ { let { startSpan = getSpan $1;+ startLabel = Just $1;+ TId _ startName = $2;+ (endSpan, conds, blocks, endLabel) = $12;+ span = getTransSpan startSpan endSpan }+ in BlIf () span startLabel (Just startName) ((Just $6):conds) ((reverse $11):blocks) endLabel }++ELSE_BLOCKS :: { (SrcSpan, [Maybe (Expression A0)], [[Block A0]], Maybe (Expression A0)) }+: maybe(INTEGER_LITERAL) elsif '(' EXPRESSION ')' then MAYBE_COMMENT NEWLINE BLOCKS ELSE_BLOCKS+ { let (endSpan, conds, blocks, endLabel) = $10+ in (endSpan, Just $4 : conds, reverse $9 : blocks, endLabel) }+| maybe(INTEGER_LITERAL) else MAYBE_COMMENT NEWLINE BLOCKS END_IF+ { let (endSpan, endLabel) = $6+ in (endSpan, [Nothing], [reverse $5], endLabel) }+| END_IF { let (endSpan, endLabel) = $1 in (endSpan, [], [], endLabel) }++END_IF :: { (SrcSpan, Maybe (Expression A0)) }+: endif { (getSpan $1, Nothing) }+| endif id { (getSpan $2, Nothing) }+| INTEGER_LITERAL endif { (getSpan $2, Just $1) }+| INTEGER_LITERAL endif id { (getSpan $3, Just $1) }++CASE_BLOCK :: { Block A0 }+: selectcase '(' EXPRESSION ')' MAYBE_COMMENT NEWLINE CASES+ { let { (caseRanges, blocks, endLabel, endSpan) = $7;+ span = getTransSpan $1 endSpan }+ in BlCase () span Nothing Nothing $3 caseRanges blocks endLabel }+| INTEGER_LITERAL selectcase '(' EXPRESSION ')' MAYBE_COMMENT NEWLINE CASES+ { let { (caseRanges, blocks, endLabel, endSpan) = $8;+ span = getTransSpan $1 endSpan }+ in BlCase () span (Just $1) Nothing $4 caseRanges blocks endLabel }+| id ':' selectcase '(' EXPRESSION ')' MAYBE_COMMENT NEWLINE CASES+ { let { (caseRanges, blocks, endLabel, endSpan) = $9;+ TId s startName = $1;+ span = getTransSpan s endSpan }+ in BlCase () span Nothing (Just startName) $5 caseRanges blocks endLabel }+| INTEGER_LITERAL id ':' selectcase '(' EXPRESSION ')' MAYBE_COMMENT NEWLINE CASES+ { let { (caseRanges, blocks, endLabel, endSpan) = $10;+ TId s startName = $2;+ span = getTransSpan s endSpan }+ in BlCase () span (Just $1) (Just startName) $6 caseRanges blocks endLabel }++-- We store line comments as statements, but this raises an issue: we have+-- nowhere to place comments after a SELECT CASE but before a CASE. So we drop+-- them. The inner CASES_ rule does /not/ use this, because comments can always+-- be parsed as belonging to to the above CASE block.+CASES :: { ([Maybe (AList Index A0)], [[Block A0]], Maybe (Expression A0), SrcSpan) }+: COMMENT_BLOCK CASES_ { $2 }+| CASES_ { $1 }++CASES_ :: { ([Maybe (AList Index A0)], [[Block A0]], Maybe (Expression A0), SrcSpan) }+: maybe(INTEGER_LITERAL) case '(' INDICIES ')' MAYBE_COMMENT NEWLINE BLOCKS CASES_+ { let (scrutinees, blocks, endLabel, endSpan) = $9+ in (Just (fromReverseList $4) : scrutinees, reverse $8 : blocks, endLabel, endSpan) }+| maybe(INTEGER_LITERAL) case default MAYBE_COMMENT NEWLINE BLOCKS END_SELECT+ { let (endLabel, endSpan) = $7+ in ([Nothing], [$6], endLabel, endSpan) }+| END_SELECT+ { let (endLabel, endSpan) = $1+ in ([], [], endLabel, endSpan) }++END_SELECT :: { (Maybe (Expression A0), SrcSpan) }+: maybe(INTEGER_LITERAL) endselect maybe(id)+ { ($1, maybe (getSpan $2) getSpan $3) }++MAYBE_EXPRESSION :: { Maybe (Expression A0) }+: EXPRESSION { Just $1 }+| {- EMPTY -} { Nothing }++MAYBE_COMMENT :: { Maybe Token }+: comment { Just $1 }+| {- EMPTY -} { Nothing }++SUBPROGRAM_UNITS2 :: { [ ProgramUnit A0 ] }+: SUBPROGRAM_UNITS SUBPROGRAM_UNIT NEWLINE { $2 : $1 }++MODULE_PROCEDURES :: { [ Block A0 ] }+: MODULE_PROCEDURES MODULE_PROCEDURE { $2 : $1 }+| MODULE_PROCEDURES MODULE_PROCEDURE COMMENT_BLOCK { $3 : $2 : $1 }+| { [ ] }++MODULE_PROCEDURE :: { Block A0 }+: moduleProcedure VARIABLES MAYBE_COMMENT NEWLINE+ { let { al = fromReverseList $2;+ st = StModuleProcedure () (getTransSpan $1 al) (fromReverseList $2) }+ in BlStatement () (getTransSpan $1 $4) Nothing st }++COMMENT_BLOCK :: { Block A0 }+: comment NEWLINE { let (TComment s c) = $1 in BlComment () s (Comment c) }++MAYBE_NEWLINE :: { Maybe Token } : NEWLINE { Just $1 } | {- EMPTY -} { Nothing }++NEWLINE :: { Token }+: NEWLINE newline { $1 }+| NEWLINE ';' { $1 }+| newline { $1 }+| ';' { $1 }++STATEMENT :: { Statement A0 }+: NONEXECUTABLE_STATEMENT { $1 }+| EXECUTABLE_STATEMENT { $1 }++EXPRESSION_ASSIGNMENT_STATEMENT :: { Statement A0 }+: DATA_REF '=' EXPRESSION { StExpressionAssign () (getTransSpan $1 $3) $1 $3 }++NONEXECUTABLE_STATEMENT :: { Statement A0 }+: DECLARATION_STATEMENT { $1 }+| intent '(' INTENT_CHOICE ')' MAYBE_DCOLON EXPRESSION_LIST+ { let expAList = fromReverseList $6+ in StIntent () (getTransSpan $1 expAList) $3 expAList }+| optional MAYBE_DCOLON EXPRESSION_LIST+ { let expAList = fromReverseList $3+ in StOptional () (getTransSpan $1 expAList) expAList }+| public MAYBE_DCOLON EXPRESSION_LIST+ { let expAList = fromReverseList $3+ in StPublic () (getTransSpan $1 expAList) (Just expAList) }+| public { StPublic () (getSpan $1) Nothing }+| private MAYBE_DCOLON EXPRESSION_LIST+ { let expAList = fromReverseList $3+ in StPrivate () (getTransSpan $1 expAList) (Just expAList) }+| private { StPrivate () (getSpan $1) Nothing }+| save MAYBE_DCOLON SAVE_ARGS+ { let saveAList = (fromReverseList $3)+ in StSave () (getTransSpan $1 saveAList) (Just saveAList) }+| save { StSave () (getSpan $1) Nothing }+| dimension MAYBE_DCOLON INITIALIZED_DECLARATOR_LIST+ { let declAList = fromReverseList $3+ in StDimension () (getTransSpan $1 declAList) declAList }+| allocatable MAYBE_DCOLON INITIALIZED_DECLARATOR_LIST+ { let declAList = fromReverseList $3+ in StAllocatable () (getTransSpan $1 declAList) declAList }+| pointer MAYBE_DCOLON INITIALIZED_DECLARATOR_LIST+ { let declAList = fromReverseList $3+ in StPointer () (getTransSpan $1 declAList) declAList }+| target MAYBE_DCOLON INITIALIZED_DECLARATOR_LIST+ { let declAList = fromReverseList $3+ in StTarget () (getTransSpan $1 declAList) declAList }+| data cDATA DATA_GROUPS cPOP+ { let dataAList = fromReverseList $3+ in StData () (getTransSpan $1 dataAList) dataAList }+| parameter '(' PARAMETER_ASSIGNMENTS ')'+ { let declAList = fromReverseList $3+ in StParameter () (getTransSpan $1 $4) declAList }+| implicit none { StImplicit () (getTransSpan $1 $2) Nothing }+| implicit cIMPLICIT IMP_LISTS cPOP+ { let impAList = fromReverseList $3+ in StImplicit () (getTransSpan $1 impAList) $ Just $ impAList }+| namelist cNAMELIST NAMELISTS cPOP+ { let nameALists = fromReverseList $3+ in StNamelist () (getTransSpan $1 nameALists) nameALists }+| equivalence EQUIVALENCE_GROUPS+ { let eqALists = fromReverseList $2+ in StEquivalence () (getTransSpan $1 eqALists) eqALists }+| common cCOMMON COMMON_GROUPS cPOP+ { let commonAList = fromReverseList $3+ in StCommon () (getTransSpan $1 commonAList) commonAList }+| external MAYBE_DCOLON VARIABLES+ { let alist = fromReverseList $3+ in StExternal () (getTransSpan $1 alist) alist }+| intrinsic MAYBE_DCOLON VARIABLES+ { let alist = fromReverseList $3+ in StIntrinsic () (getTransSpan $1 alist) alist }+| use VARIABLE { StUse () (getTransSpan $1 $2) $2 Nothing Permissive Nothing }+| use VARIABLE ',' RENAME_LIST+ { let alist = fromReverseList $4+ in StUse () (getTransSpan $1 alist) $2 Nothing Permissive (Just alist) }+| use VARIABLE ',' only ':' MAYBE_RENAME_LIST+ { StUse () (getTransSpan $1 ($5, $6)) $2 Nothing Exclusive $6 }+| entry VARIABLE MAYBE_RESULT+ { StEntry () (getTransSpan $1 $ maybe (getSpan $2) getSpan $3) $2 Nothing $3 }+| entry VARIABLE '(' ')' MAYBE_RESULT+ { StEntry () (getTransSpan $1 $ maybe (getSpan $4) getSpan $5) $2 Nothing $5 }+| entry VARIABLE '(' VARIABLES ')' MAYBE_RESULT+ { StEntry () (getTransSpan $1 $ maybe (getSpan $5) getSpan $6) $2 (Just $ fromReverseList $4) $6 }+| sequence { StSequence () (getSpan $1) }+| type ATTRIBUTE_LIST '::' id+ { let { TId span id = $4;+ alist = if null $2 then Nothing else (Just . fromReverseList) $2 }+ in StType () (getTransSpan $1 span) alist id }+| type id+ { let TId span id = $2 in StType () (getTransSpan $1 span) Nothing id }+| endType { StEndType () (getSpan $1) Nothing }+| endType id+ { let TId span id = $2 in StEndType () (getTransSpan $1 span) (Just id) }+| include STRING { StInclude () (getTransSpan $1 $2) $2 Nothing }+-- Following is a fake node to make arbitrary FORMAT statements parsable.+-- Must be fixed in the future. TODO+| format blob+ { let TBlob s blob = $2 in StFormatBogus () (getTransSpan $1 s) blob }++EXECUTABLE_STATEMENT :: { Statement A0 }+: allocate '(' DATA_REFS MAYBE_ALLOC_OPT_LIST ')'+ { StAllocate () (getTransSpan $1 $5) Nothing (fromReverseList $3) $4 }+| nullify '(' DATA_REFS ')'+ { StNullify () (getTransSpan $1 $4) (fromReverseList $3) }+| deallocate '(' DATA_REFS MAYBE_ALLOC_OPT_LIST ')'+ { StDeallocate () (getTransSpan $1 $5) (fromReverseList $3) $4 }+| EXPRESSION_ASSIGNMENT_STATEMENT { $1 }+| DATA_REF '=>' EXPRESSION { StPointerAssign () (getTransSpan $1 $3) $1 $3 }+| where '(' EXPRESSION ')' EXPRESSION_ASSIGNMENT_STATEMENT+ { StWhere () (getTransSpan $1 $5) $3 $5 }+| where '(' EXPRESSION ')' { StWhereConstruct () (getTransSpan $1 $4) Nothing $3 }+| elsewhere '(' EXPRESSION ')' { StElsewhere () (getTransSpan $1 $4) Nothing (Just $3) }+| elsewhere { StElsewhere () (getSpan $1) Nothing Nothing }+| endwhere { StEndWhere () (getSpan $1) Nothing }+| if '(' EXPRESSION ')' INTEGER_LITERAL ',' INTEGER_LITERAL ',' INTEGER_LITERAL+ { StIfArithmetic () (getTransSpan $1 $9) $3 $5 $7 $9 }+| do { StDo () (getSpan $1) Nothing Nothing Nothing }+| id ':' do+ { let TId s id = $1+ in StDo () (getTransSpan s $3) (Just id) Nothing Nothing }+| do INTEGER_LITERAL MAYBE_COMMA DO_SPECIFICATION+ { StDo () (getTransSpan $1 $4) Nothing (Just $2) (Just $4) }+| do DO_SPECIFICATION { StDo () (getTransSpan $1 $2) Nothing Nothing (Just $2) }+| id ':' do DO_SPECIFICATION+ { let TId s id = $1+ in StDo () (getTransSpan s $4) (Just id) Nothing (Just $4) }+| do INTEGER_LITERAL MAYBE_COMMA while '(' EXPRESSION ')'+ { StDoWhile () (getTransSpan $1 $7) Nothing (Just $2) $6 }+| do while '(' EXPRESSION ')'+ { StDoWhile () (getTransSpan $1 $5) Nothing Nothing $4 }+| id ':' do while '(' EXPRESSION ')'+ { let TId s id = $1+ in StDoWhile () (getTransSpan s $7) (Just id) Nothing $6 }+| enddo { StEnddo () (getSpan $1) Nothing }+| enddo id+ { let TId s id = $2 in StEnddo () (getTransSpan $1 s) (Just id) }+| cycle { StCycle () (getSpan $1) Nothing }+| cycle VARIABLE { StCycle () (getTransSpan $1 $2) (Just $2) }+| exit { StExit () (getSpan $1) Nothing }+| exit VARIABLE { StExit () (getTransSpan $1 $2) (Just $2) }+-- GO TO label+| goto INTEGER_LITERAL { StGotoUnconditional () (getTransSpan $1 $2) $2 }+-- GO TO scalar-int-variable+| goto VARIABLE { StGotoUnconditional () (getTransSpan $1 $2) $2 }+-- GO TO scalar-int-variable [,] label-list+| goto VARIABLE MAYBE_COMMA '(' INTEGERS ')'+ { StGotoAssigned () (getTransSpan $1 $6) $2 (Just (fromReverseList $5)) }+-- GO TO label-list [,] scalar-int-expression+| goto '(' INTEGERS ')' MAYBE_COMMA EXPRESSION+ { StGotoComputed () (getTransSpan $1 $6) (fromReverseList $3) $6 }+| assign INTEGER_LITERAL to VARIABLE+ { StLabelAssign () (getTransSpan $1 $4) $2 $4 }+| continue { StContinue () (getSpan $1) }+| stop { StStop () (getSpan $1) Nothing }+| stop EXPRESSION { StStop () (getTransSpan $1 $2) (Just $2) }+| pause { StPause () (getSpan $1) Nothing }+| pause EXPRESSION { StPause () (getTransSpan $1 $2) (Just $2) }+| if '(' EXPRESSION ')' EXECUTABLE_STATEMENT+ { StIfLogical () (getTransSpan $1 $5) $3 $5 }+| read CILIST IN_IOLIST+ { let alist = fromReverseList $3+ in StRead () (getTransSpan $1 alist) $2 (Just alist) }+| read CILIST { StRead () (getTransSpan $1 $2) $2 Nothing }+| read FORMAT_ID ',' IN_IOLIST+ { let alist = fromReverseList $4+ in StRead2 () (getTransSpan $1 alist) $2 (Just alist) }+| read FORMAT_ID { StRead2 () (getTransSpan $1 $2) $2 Nothing }+| write CILIST OUT_IOLIST+ { let alist = fromReverseList $3+ in StWrite () (getTransSpan $1 alist) $2 (Just alist) }+| write CILIST { StWrite () (getTransSpan $1 $2) $2 Nothing }+| print FORMAT_ID ',' OUT_IOLIST+ { let alist = fromReverseList $4+ in StPrint () (getTransSpan $1 alist) $2 (Just alist) }+| print FORMAT_ID { StPrint () (getTransSpan $1 $2) $2 Nothing }+| open CILIST { StOpen () (getTransSpan $1 $2) $2 }+| close CILIST { StClose () (getTransSpan $1 $2) $2 }+| inquire CILIST { StInquire () (getTransSpan $1 $2) $2 }+| rewind CILIST { StRewind () (getTransSpan $1 $2) $2 }+| rewind UNIT { StRewind2 () (getTransSpan $1 $2) $2 }+| endfile CILIST { StEndfile () (getTransSpan $1 $2) $2 }+| endfile UNIT { StEndfile2 () (getTransSpan $1 $2) $2 }+| backspace CILIST { StBackspace () (getTransSpan $1 $2) $2 }+| backspace UNIT { StBackspace2 () (getTransSpan $1 $2) $2 }+| call VARIABLE { StCall () (getTransSpan $1 $2) $2 Nothing }+| call VARIABLE '(' ')' { StCall () (getTransSpan $1 $4) $2 Nothing }+| call VARIABLE '(' ARGUMENTS ')'+ { let alist = fromReverseList $4+ in StCall () (getTransSpan $1 $5) $2 (Just alist) }+| return { StReturn () (getSpan $1) Nothing }+| return EXPRESSION { StReturn () (getTransSpan $1 $2) (Just $2) }++ARGUMENTS :: { [ Argument A0 ] }+: ARGUMENTS ',' ARGUMENT { $3 : $1 }+| ARGUMENT { [ $1 ] }++ARGUMENT :: { Argument A0 }+: id '=' EXPRESSION+ { let TId span keyword = $1+ in Argument () (getTransSpan span $3) (Just keyword) (ArgExpr $3) }+| '(' VARIABLE ')'+ { let ExpValue _ _ (ValVariable v) = $2+ in Argument () (getTransSpan $1 $3) Nothing (ArgExprVar () (getSpan $2) v) }+| EXPRESSION+ { Argument () (getSpan $1) Nothing (ArgExpr $1) }++MAYBE_RENAME_LIST :: { Maybe (AList Use A0) }+: RENAME_LIST { Just $ fromReverseList $1 }+| {- empty -} { Nothing }++RENAME_LIST :: { [ Use A0 ] }+: RENAME_LIST ',' RENAME { $3 : $1 }+| RENAME { [ $1 ] }++RENAME :: { Use A0 }+: VARIABLE '=>' VARIABLE { UseRename () (getTransSpan $1 $3) $1 $3 }+| VARIABLE { UseID () (getSpan $1) $1 }+| operator '(' opCustom ')'+ { let TOpCustom ss op = $3+ in UseID () (getTransSpan $1 $4) (ExpValue () ss (ValOperator op)) }+| assignment { UseID () (getSpan $1) (ExpValue () (getSpan $1) ValAssignment) }++MAYBE_DCOLON :: { () } : '::' { () } | {- EMPTY -} { () }++FORMAT_ID :: { Expression A0 }+: FORMAT_ID '/' '/' FORMAT_ID %prec CONCAT+ { ExpBinary () (getTransSpan $1 $4) Concatenation $1 $4 }+| INTEGER_LITERAL { $1 }+| STRING { $1 }+| DATA_REF { $1 }+| '*' { ExpValue () (getSpan $1) ValStar }++UNIT :: { Expression A0 }+: INTEGER_LITERAL { $1 }+| DATA_REF { $1 }+| '*' { ExpValue () (getSpan $1) ValStar }++CILIST :: { AList ControlPair A0 }+: '(' CILIST_ELEMENT ',' FORMAT_ID ',' CILIST_PAIRS ')'+ { let { cp1 = ControlPair () (getSpan $2) Nothing $2;+ cp2 = ControlPair () (getSpan $4) Nothing $4;+ tail = fromReverseList $6 }+ in setSpan (getTransSpan $1 $7) $ cp1 `aCons` cp2 `aCons` tail }+| '(' CILIST_ELEMENT ',' FORMAT_ID ')'+ { let { cp1 = ControlPair () (getSpan $2) Nothing $2;+ cp2 = ControlPair () (getSpan $4) Nothing $4 }+ in AList () (getTransSpan $1 $5) [ cp1, cp2 ] }+| '(' CILIST_ELEMENT ',' CILIST_PAIRS ')'+ { let { cp1 = ControlPair () (getSpan $2) Nothing $2;+ tail = fromReverseList $4 }+ in setSpan (getTransSpan $1 $5) $ cp1 `aCons` tail }+| '(' CILIST_ELEMENT ')'+ { let cp1 = ControlPair () (getSpan $2) Nothing $2+ in AList () (getTransSpan $1 $3) [ cp1 ] }+| '(' CILIST_PAIRS ')' { fromReverseList $2 }++CILIST_PAIRS :: { [ ControlPair A0 ] }+: CILIST_PAIRS ',' CILIST_PAIR { $3 : $1 }+| CILIST_PAIR { [ $1 ] }++CILIST_PAIR :: { ControlPair A0 }+: id '=' CILIST_ELEMENT+ { let (TId s id) = $1 in ControlPair () (getTransSpan s $3) (Just id) $3 }++CILIST_ELEMENT :: { Expression A0 }+: CI_EXPRESSION { $1 }+| '*' { ExpValue () (getSpan $1) ValStar }++CI_EXPRESSION :: { Expression A0 }+: CI_EXPRESSION '+' CI_EXPRESSION+ { ExpBinary () (getTransSpan $1 $3) Addition $1 $3 }+| CI_EXPRESSION '-' CI_EXPRESSION+ { ExpBinary () (getTransSpan $1 $3) Subtraction $1 $3 }+| CI_EXPRESSION '*' CI_EXPRESSION+ { ExpBinary () (getTransSpan $1 $3) Multiplication $1 $3 }+| CI_EXPRESSION '/' CI_EXPRESSION+ { ExpBinary () (getTransSpan $1 $3) Division $1 $3 }+| CI_EXPRESSION '**' CI_EXPRESSION+ { ExpBinary () (getTransSpan $1 $3) Exponentiation $1 $3 }+| CI_EXPRESSION '/' '/' CI_EXPRESSION %prec CONCAT+ { ExpBinary () (getTransSpan $1 $4) Concatenation $1 $4 }+| ARITHMETIC_SIGN CI_EXPRESSION %prec SIGN+ { ExpUnary () (getTransSpan (fst $1) $2) (snd $1) $2 }+| CI_EXPRESSION or CI_EXPRESSION+ { ExpBinary () (getTransSpan $1 $3) Or $1 $3 }+| CI_EXPRESSION and CI_EXPRESSION+ { ExpBinary () (getTransSpan $1 $3) And $1 $3 }+| not CI_EXPRESSION+ { ExpUnary () (getTransSpan $1 $2) Not $2 }+| CI_EXPRESSION eqv CI_EXPRESSION+ { ExpBinary () (getTransSpan $1 $3) Equivalent $1 $3 }+| CI_EXPRESSION neqv CI_EXPRESSION+ { ExpBinary () (getTransSpan $1 $3) NotEquivalent $1 $3 }+| CI_EXPRESSION RELATIONAL_OPERATOR CI_EXPRESSION %prec RELATIONAL+ { ExpBinary () (getTransSpan $1 $3) $2 $1 $3 }+| opCustom CI_EXPRESSION %prec DEFINED_UNARY+ { let TOpCustom span str = $1+ in ExpUnary () (getTransSpan span $2) (UnCustom str) $2 }+| CI_EXPRESSION opCustom CI_EXPRESSION+ { let TOpCustom _ str = $2+ in ExpBinary () (getTransSpan $1 $3) (BinCustom str) $1 $3 }+| '(' CI_EXPRESSION ')' { setSpan (getTransSpan $1 $3) $2 }+| INTEGER_LITERAL { $1 }+| LOGICAL_LITERAL { $1 }+| STRING { $1 }+| DATA_REF { $1 }++MAYBE_ALLOC_OPT_LIST :: { Maybe (AList AllocOpt A0) }+: ',' stat '=' EXPRESSION { Just (fromReverseList [AOStat () (getTransSpan $2 $4) $4]) }+| {- empty -} { Nothing }++IN_IOLIST :: { [ Expression A0 ] }+: IN_IOLIST ',' IN_IO_ELEMENT { $3 : $1}+| IN_IO_ELEMENT { [ $1 ] }++IN_IO_ELEMENT :: { Expression A0 }+: DATA_REF { $1 }+| '(' IN_IOLIST ',' DO_SPECIFICATION ')'+ { ExpImpliedDo () (getTransSpan $1 $5) (fromReverseList $2) $4 }++OUT_IOLIST :: { [ Expression A0 ] }+: OUT_IOLIST ',' EXPRESSION { $3 : $1}+| EXPRESSION { [ $1 ] }++COMMON_GROUPS :: { [ CommonGroup A0 ] }+: COMMON_GROUPS COMMON_GROUP { $2 : $1 }+| COMMON_GROUPS ',2' COMMON_GROUP { $3 : $1 }+| INIT_COMMON_GROUP { [ $1 ] }++COMMON_GROUP :: { CommonGroup A0 }+: COMMON_NAME UNINITIALIZED_DECLARATOR_LIST+ { let alist = fromReverseList $2+ in CommonGroup () (getTransSpan $1 alist) (Just $1) alist }+| '/' '/' UNINITIALIZED_DECLARATOR_LIST+ { let alist = fromReverseList $3+ in CommonGroup () (getTransSpan $1 alist) Nothing alist }++INIT_COMMON_GROUP :: { CommonGroup A0 }+: COMMON_NAME UNINITIALIZED_DECLARATOR_LIST+ { let alist = fromReverseList $2+ in CommonGroup () (getTransSpan $1 alist) (Just $1) alist }+| '/' '/' UNINITIALIZED_DECLARATOR_LIST+ { let alist = fromReverseList $3+ in CommonGroup () (getTransSpan $1 alist) Nothing alist }+| UNINITIALIZED_DECLARATOR_LIST+ { let alist = fromReverseList $1+ in CommonGroup () (getSpan alist) Nothing alist }++EQUIVALENCE_GROUPS :: { [ AList Expression A0 ] }+: EQUIVALENCE_GROUPS ',' '(' PART_REFS ')'+ { setSpan (getTransSpan $3 $5) (fromReverseList $4) : $1 }+| '(' PART_REFS ')'+ { [ setSpan (getTransSpan $1 $3) (fromReverseList $2) ] }++NAMELISTS :: { [ Namelist A0 ] }+: NAMELISTS NAMELIST { $2 : $1 }+| NAMELISTS ',2' NAMELIST { $3 : $1 }+| NAMELIST { [ $1 ] }++NAMELIST :: { Namelist A0 }+: '/' VARIABLE '/' VARIABLES+ { Namelist () (getTransSpan $1 $4) $2 $ fromReverseList $4 }++MAYBE_VARIABLES :: { Maybe (AList Expression A0) }+: VARIABLES { Just $ fromReverseList $1 } | {- EMPTY -} { Nothing }++VARIABLES :: { [ Expression A0 ] }+: VARIABLES ',' VARIABLE { $3 : $1 }+| VARIABLE { [ $1 ] }++IMP_LISTS :: { [ ImpList A0 ] }+: IMP_LISTS ',' IMP_LIST { $3 : $1 }+| IMP_LIST { [ $1 ] }++IMP_LIST :: { ImpList A0 }+: TYPE_SPEC '(2' IMP_ELEMENTS ')'+ { ImpList () (getTransSpan $1 $4) $1 (aReverse $3) }++IMP_ELEMENTS :: { AList ImpElement A0 }+: IMP_ELEMENTS ',' IMP_ELEMENT { setSpan (getTransSpan $1 $3) $ $3 `aCons` $1 }+| IMP_ELEMENT { AList () (getSpan $1) [ $1 ] }++IMP_ELEMENT :: { ImpElement A0 }+: id {% do+ let (TId s id) = $1+ if length id /= 1+ then fail "Implicit argument must be a character."+ else return $ ImpCharacter () s id+ }+| id '-' id {% do+ let (TId _ id1) = $1+ let (TId _ id2) = $3+ if length id1 /= 1 || length id2 /= 1+ then fail "Implicit argument must be a character."+ else return $ ImpRange () (getTransSpan $1 $3) id1 id2+ }++PARAMETER_ASSIGNMENTS :: { [ Declarator A0 ] }+: PARAMETER_ASSIGNMENTS ',' PARAMETER_ASSIGNMENT { $3 : $1 }+| PARAMETER_ASSIGNMENT { [ $1 ] }++PARAMETER_ASSIGNMENT :: { Declarator A0 }+: VARIABLE '=' EXPRESSION+ { Declarator () (getTransSpan $1 $3) $1 ScalarDecl Nothing (Just $3) }++DECLARATION_STATEMENT :: { Statement A0 }+: TYPE_SPEC ATTRIBUTE_LIST '::' INITIALIZED_DECLARATOR_LIST+ { let { mAttrAList = if null $2 then Nothing else Just $ fromReverseList $2;+ declAList = fromReverseList $4 }+ in StDeclaration () (getTransSpan $1 declAList) $1 mAttrAList declAList }+| TYPE_SPEC INITIALIZED_DECLARATOR_LIST+ { let { declAList = fromReverseList $2 }+ in StDeclaration () (getTransSpan $1 declAList) $1 Nothing declAList }++ATTRIBUTE_LIST :: { [ Attribute A0 ] }+: ATTRIBUTE_LIST ',' ATTRIBUTE_SPEC { $3 : $1 }+| {- EMPTY -} { [ ] }++ATTRIBUTE_SPEC :: { Attribute A0 }+: public { AttrPublic () (getSpan $1) }+| private { AttrPrivate () (getSpan $1) }+| allocatable { AttrAllocatable () (getSpan $1) }+| dimension '(' DIMENSION_DECLARATORS ')'+ { AttrDimension () (getTransSpan $1 $4) (aReverse $3) }+| external { AttrExternal () (getSpan $1) }+| intent '(' INTENT_CHOICE ')' { AttrIntent () (getTransSpan $1 $4) $3 }+| intrinsic { AttrIntrinsic () (getSpan $1) }+| optional { AttrOptional () (getSpan $1) }+| pointer { AttrPointer () (getSpan $1) }+| parameter { AttrParameter () (getSpan $1) }+| save { AttrSave () (getSpan $1) }+| target { AttrTarget () (getSpan $1) }++INTENT_CHOICE :: { Intent } : in { In } | out { Out } | inout { InOut }++DATA_GROUPS :: { [ DataGroup A0 ] }+: DATA_GROUPS MAYBE_COMMA DATA_LIST slash EXPRESSION_LIST slash+ { let { nameAList = fromReverseList $3;+ dataAList = fromReverseList $5 }+ in DataGroup () (getTransSpan nameAList $6) nameAList dataAList : $1 }+| DATA_LIST slash EXPRESSION_LIST slash+ { let { nameAList = fromReverseList $1;+ dataAList = fromReverseList $3 }+ in [ DataGroup () (getTransSpan nameAList $4) nameAList dataAList ] }++MAYBE_COMMA :: { () } : ',' { () } | {- EMPTY -} { () }++DATA_LIST :: { [ Expression A0 ] }+: DATA_LIST ',' DATA_ELEMENT { $3 : $1 }+| DATA_ELEMENT { [ $1 ] }++DATA_ELEMENT :: { Expression A0 }+: DATA_REF { $1 } | IMPLIED_DO { $1 }++SAVE_ARGS :: { [ Expression A0 ] }+: SAVE_ARGS ',' SAVE_ARG { $3 : $1 } | SAVE_ARG { [ $1 ] }++SAVE_ARG :: { Expression A0 } : COMMON_NAME { $1 } | VARIABLE { $1 }++COMMON_NAME :: { Expression A0 }+: '/' VARIABLE '/' { setSpan (getTransSpan $1 $3) $2 }++INITIALIZED_DECLARATOR_LIST :: { [ Declarator A0 ] }+: INITIALIZED_DECLARATOR_LIST ',' INITIALIZED_DECLARATOR { $3 : $1 }+| INITIALIZED_DECLARATOR { [ $1 ] }++UNINITIALIZED_DECLARATOR_LIST :: { [ Declarator A0 ] }+: UNINITIALIZED_DECLARATOR_LIST ',' DECLARATOR { $3 : $1 }+| DECLARATOR { [ $1 ] }++INITIALIZED_DECLARATOR :: { Declarator A0 }+: DECLARATOR '=' EXPRESSION { setInitialisation $1 $3 }+| DECLARATOR '=>' EXPRESSION { setInitialisation $1 $3 }+| DECLARATOR { $1 }++DECLARATOR :: { Declarator A0 }+: VARIABLE+ { Declarator () (getSpan $1) $1 ScalarDecl Nothing Nothing }+| VARIABLE '*' EXPRESSION+ { Declarator () (getTransSpan $1 $3) $1 ScalarDecl (Just $3) Nothing }+| VARIABLE '*' '(' '*' ')'+ { let star = ExpValue () (getSpan $4) ValStar+ in Declarator () (getTransSpan $1 $5) $1 ScalarDecl (Just star) Nothing }+| VARIABLE '(' DIMENSION_DECLARATORS ')'+ { Declarator () (getTransSpan $1 $4) $1 (ArrayDecl (aReverse $3)) Nothing Nothing }+| VARIABLE '(' DIMENSION_DECLARATORS ')' '*' EXPRESSION+ { Declarator () (getTransSpan $1 $6) $1 (ArrayDecl (aReverse $3)) (Just $6) Nothing }+-- nonstandard char array syntax (wrong order for dimensions & charlen)+| VARIABLE '*' EXPRESSION '(' DIMENSION_DECLARATORS ')'+ { Declarator () (getTransSpan $1 $6) $1 (ArrayDecl (aReverse $5)) (Just $3) Nothing }+| VARIABLE '(' DIMENSION_DECLARATORS ')' '*' '(' '*' ')'+ { let star = ExpValue () (getSpan $7) ValStar+ in Declarator () (getTransSpan $1 $8) $1 (ArrayDecl (aReverse $3)) (Just star) Nothing }++DIMENSION_DECLARATORS :: { AList DimensionDeclarator A0 }+: DIMENSION_DECLARATORS ',' DIMENSION_DECLARATOR+ { setSpan (getTransSpan $1 $3) $ $3 `aCons` $1 }+| DIMENSION_DECLARATOR+ { AList () (getSpan $1) [ $1 ] }++DIMENSION_DECLARATOR :: { DimensionDeclarator A0 }+: EXPRESSION ':' EXPRESSION+ { DimensionDeclarator () (getTransSpan $1 $3) (Just $1) (Just $3) }+| EXPRESSION { DimensionDeclarator () (getSpan $1) Nothing (Just $1) }+-- Lower bound only+| EXPRESSION ':'+ { DimensionDeclarator () (getTransSpan $1 $2) (Just $1) Nothing }+| EXPRESSION ':' '*'+ { let { span = getSpan $3;+ star = ExpValue () span ValStar }+ in DimensionDeclarator () (getTransSpan $1 span) (Just $1) (Just star) }+| '*'+ { let { span = getSpan $1;+ star = ExpValue () span ValStar }+ in DimensionDeclarator () span Nothing (Just star) }+| ':'+ { let span = getSpan $1+ in DimensionDeclarator () span Nothing Nothing }++TYPE_SPEC :: { TypeSpec A0 }+: integer KIND_SELECTOR { TypeSpec () (getSpan ($1, $2)) TypeInteger $2 }+| real KIND_SELECTOR { TypeSpec () (getSpan ($1, $2)) TypeReal $2 }+| doublePrecision { TypeSpec () (getSpan $1) TypeDoublePrecision Nothing }+| complex KIND_SELECTOR { TypeSpec () (getSpan ($1, $2)) TypeComplex $2 }+| character CHAR_SELECTOR { TypeSpec () (getSpan ($1, $2)) TypeCharacter $2 }+| logical KIND_SELECTOR { TypeSpec () (getSpan ($1, $2)) TypeLogical $2 }+| type '(' id ')'+ { let TId _ id = $3+ in TypeSpec () (getTransSpan $1 $4) (TypeCustom id) Nothing }++KIND_SELECTOR :: { Maybe (Selector A0) }+: '(' EXPRESSION ')'+ { Just $ Selector () (getTransSpan $1 $3) Nothing (Just $2) }+| '(' kind '=' EXPRESSION ')'+ { Just $ Selector () (getTransSpan $1 $5) Nothing (Just $4) }+| '*' EXPRESSION -- non-standard but commonly used extension+ { Just $ Selector () (getTransSpan $1 $2) Nothing (Just $2) }+| {- EMPTY -} { Nothing }++CHAR_SELECTOR :: { Maybe (Selector A0) }+: '*' EXPRESSION+ { Just $ Selector () (getTransSpan $1 $2) (Just $2) Nothing }+-- The following rule is a bug in the spec.+-- | '*' EXPRESSION ','+-- { Just $ Selector () (getTransSpan $1 $2) (Just $2) Nothing }+| '*' '(' '*' ')'+ { let star = ExpValue () (getSpan $3) ValStar+ in Just $ Selector () (getTransSpan $1 $4) (Just star) Nothing }+| '(' LEN_EXPRESSION ')'+ { Just $ Selector () (getTransSpan $1 $3) (Just $2) Nothing }+| '(' len '=' LEN_EXPRESSION ')'+ { Just $ Selector () (getTransSpan $1 $5) (Just $4) Nothing }+| '(' kind '=' EXPRESSION ')'+ { Just $ Selector () (getTransSpan $1 $5) Nothing (Just $4) }+| '(' LEN_EXPRESSION ',' EXPRESSION ')'+ { Just $ Selector () (getTransSpan $1 $5) (Just $2) (Just $4) }+| '(' LEN_EXPRESSION ',' kind '=' EXPRESSION ')'+ { Just $ Selector () (getTransSpan $1 $7) (Just $2) (Just $6) }+| '(' len '=' LEN_EXPRESSION ',' kind '=' EXPRESSION ')'+ { Just $ Selector () (getTransSpan $1 $9) (Just $4) (Just $8) }+| '(' kind '=' EXPRESSION ',' len '=' LEN_EXPRESSION ')'+ { Just $ Selector () (getTransSpan $1 $9) (Just $8) (Just $4) }+| {- EMPTY -} { Nothing }++LEN_EXPRESSION :: { Expression A0 }+: EXPRESSION { $1 }+| '*' { ExpValue () (getSpan $1) ValStar }++EXPRESSION :: { Expression A0 }+: EXPRESSION '+' EXPRESSION+ { ExpBinary () (getTransSpan $1 $3) Addition $1 $3 }+| EXPRESSION '-' EXPRESSION+ { ExpBinary () (getTransSpan $1 $3) Subtraction $1 $3 }+| EXPRESSION '*' EXPRESSION+ { ExpBinary () (getTransSpan $1 $3) Multiplication $1 $3 }+| EXPRESSION '/' EXPRESSION+ { ExpBinary () (getTransSpan $1 $3) Division $1 $3 }+| EXPRESSION '**' EXPRESSION+ { ExpBinary () (getTransSpan $1 $3) Exponentiation $1 $3 }+| EXPRESSION '/' '/' EXPRESSION %prec CONCAT+ { ExpBinary () (getTransSpan $1 $4) Concatenation $1 $4 }+| ARITHMETIC_SIGN EXPRESSION %prec SIGN+ { ExpUnary () (getTransSpan (fst $1) $2) (snd $1) $2 }+| EXPRESSION or EXPRESSION+ { ExpBinary () (getTransSpan $1 $3) Or $1 $3 }+| EXPRESSION and EXPRESSION+ { ExpBinary () (getTransSpan $1 $3) And $1 $3 }+| not EXPRESSION+ { ExpUnary () (getTransSpan $1 $2) Not $2 }+| EXPRESSION eqv EXPRESSION+ { ExpBinary () (getTransSpan $1 $3) Equivalent $1 $3 }+| EXPRESSION neqv EXPRESSION+ { ExpBinary () (getTransSpan $1 $3) NotEquivalent $1 $3 }+| EXPRESSION RELATIONAL_OPERATOR EXPRESSION %prec RELATIONAL+ { ExpBinary () (getTransSpan $1 $3) $2 $1 $3 }+| opCustom EXPRESSION %prec DEFINED_UNARY+ { let TOpCustom span str = $1+ in ExpUnary () (getTransSpan span $2) (UnCustom str) $2 }+| EXPRESSION opCustom EXPRESSION+ { let TOpCustom _ str = $2+ in ExpBinary () (getTransSpan $1 $3) (BinCustom str) $1 $3 }+| '(' EXPRESSION ')' { setSpan (getTransSpan $1 $3) $2 }+| NUMERIC_LITERAL { $1 }+| '(' EXPRESSION ',' EXPRESSION ')'+ { ExpValue () (getTransSpan $1 $5) (ValComplex $2 $4) }+| LOGICAL_LITERAL { $1 }+| STRING { $1 }+| DATA_REF { $1 }+| IMPLIED_DO { $1 }+| '(/' EXPRESSION_LIST '/)'+ { ExpInitialisation () (getTransSpan $1 $3) (fromReverseList $2) }+| operator '(' opCustom ')'+ { let TOpCustom _ op = $3+ in ExpValue () (getTransSpan $1 $4) (ValOperator op) }+| assignment { ExpValue () (getSpan $1) ValAssignment }+| '*' INTEGER_LITERAL { ExpReturnSpec () (getTransSpan $1 $2) $2 }++DATA_REFS :: { [ Expression A0 ] }+: DATA_REFS ',' DATA_REF { $3 : $1 }+| DATA_REF { [ $1 ] }++DATA_REF :: { Expression A0 }+: DATA_REF '%' PART_REF { ExpDataRef () (getTransSpan $1 $3) $1 $3 }+| PART_REF { $1 }++PART_REFS :: { [ Expression A0 ] }+: PART_REFS ',' PART_REF { $3 : $1 }+| PART_REF { [ $1 ] }++PART_REF :: { Expression A0 }+: VARIABLE { $1 }+| VARIABLE '(' ')'+ { ExpFunctionCall () (getTransSpan $1 $3) $1 Nothing }+| VARIABLE '(' INDICIES ')'+ { ExpSubscript () (getTransSpan $1 $4) $1 (fromReverseList $3) }+| VARIABLE '(' INDICIES ')' '(' INDICIES ')'+ { let innerSub = ExpSubscript () (getTransSpan $1 $4) $1 (fromReverseList $3)+ in ExpSubscript () (getTransSpan $1 $7) innerSub (fromReverseList $6) }++INDICIES :: { [ Index A0 ] }+: INDICIES ',' INDEX { $3 : $1 }+| INDEX { [ $1 ] }++INDEX :: { Index A0 }+: RANGE { $1 }+| RANGE ':' EXPRESSION+ { let IxRange () s lower upper _ = $1+ in IxRange () (getTransSpan s $3) lower upper (Just $3) }+| EXPRESSION { IxSingle () (getSpan $1) Nothing $1 }+-- Following is only as an intermediate stage before having been turned into+-- an argument by later transformation.+| id '=' EXPRESSION+ { let TId s id = $1 in IxSingle () (getTransSpan $1 s) (Just id) $3 }++RANGE :: { Index A0 }+: ':' { IxRange () (getSpan $1) Nothing Nothing Nothing }+| ':' EXPRESSION { IxRange () (getTransSpan $1 $2) Nothing (Just $2) Nothing }+| EXPRESSION ':' { IxRange () (getTransSpan $1 $2) (Just $1) Nothing Nothing }+| EXPRESSION ':' EXPRESSION+ { IxRange () (getTransSpan $1 $3) (Just $1) (Just $3) Nothing }++DO_SPECIFICATION :: { DoSpecification A0 }+: EXPRESSION_ASSIGNMENT_STATEMENT ',' EXPRESSION ',' EXPRESSION+ { DoSpecification () (getTransSpan $1 $5) $1 $3 (Just $5) }+| EXPRESSION_ASSIGNMENT_STATEMENT ',' EXPRESSION+ { DoSpecification () (getTransSpan $1 $3) $1 $3 Nothing }++IMPLIED_DO :: { Expression A0 }+: '(' EXPRESSION ',' DO_SPECIFICATION ')'+ { let expList = AList () (getSpan $2) [ $2 ]+ in ExpImpliedDo () (getTransSpan $1 $5) expList $4 }+| '(' EXPRESSION ',' EXPRESSION ',' DO_SPECIFICATION ')'+ { let expList = AList () (getTransSpan $2 $4) [ $2, $4 ]+ in ExpImpliedDo () (getTransSpan $1 $5) expList $6 }+| '(' EXPRESSION ',' EXPRESSION ',' EXPRESSION_LIST ',' DO_SPECIFICATION ')'+ { let { exps = reverse $6;+ expList = AList () (getTransSpan $2 exps) ($2 : $4 : reverse $6) }+ in ExpImpliedDo () (getTransSpan $1 $9) expList $8 }++EXPRESSION_LIST :: { [ Expression A0 ] }+: EXPRESSION_LIST ',' EXPRESSION { $3 : $1 }+| EXPRESSION { [ $1 ] }++ARITHMETIC_SIGN :: { (SrcSpan, UnaryOp) }+: '-' { (getSpan $1, Minus) }+| '+' { (getSpan $1, Plus) }++RELATIONAL_OPERATOR :: { BinaryOp }+: '==' { EQ }+| '!=' { NE }+| '>' { GT }+| '>=' { GTE }+| '<' { LT }+| '<=' { LTE }++VARIABLE :: { Expression A0 }+: id { ExpValue () (getSpan $1) $ let (TId _ s) = $1 in ValVariable s }++NUMERIC_LITERAL :: { Expression A0 }+: INTEGER_LITERAL { $1 } | REAL_LITERAL { $1 }++INTEGERS :: { [ Expression A0 ] }+: INTEGERS ',' INTEGER_LITERAL { $3 : $1 }+| INTEGER_LITERAL { [ $1 ] }++INTEGER_LITERAL :: { Expression A0 }+: int+ { let TIntegerLiteral s i = $1+ in ExpValue () s $ ValInteger i Nothing }+| int '_' KIND_PARAM+ { let TIntegerLiteral s i = $1+ in ExpValue () s $ ValInteger i (Just $3) }+| boz { let TBozLiteral s b = $1 in ExpValue () s $ ValBoz b }++REAL_LITERAL :: { Expression A0 }+: float+ { let TRealLiteral s r = $1+ in ExpValue () s $ ValReal r Nothing }+| float '_' KIND_PARAM+ { let TRealLiteral s r = $1+ in ExpValue () s $ ValReal r (Just $3) }++LOGICAL_LITERAL :: { Expression A0 }+: bool+ { let TLogicalLiteral s b = $1+ in ExpValue () s (ValLogical b Nothing) }+| bool '_' KIND_PARAM+ { let TLogicalLiteral s b = $1+ in ExpValue () s (ValLogical b (Just $3)) }++KIND_PARAM :: { Expression A0 }+: INTEGER_LITERAL { $1 }+| VARIABLE { $1 }++STRING :: { Expression A0 }+: string { let TString s c = $1 in ExpValue () s $ ValString c }++cDATA :: { () } : {% pushContext ConData }+cIMPLICIT :: { () } : {% pushContext ConImplicit }+cNAMELIST :: { () } : {% pushContext ConNamelist }+cCOMMON :: { () } : {% pushContext ConCommon }+cPOP :: { () } : {% popContext }
+ src/Language/Fortran/Parser/Free/Fortran95.y view
@@ -0,0 +1,1231 @@+-- -*- Mode: Haskell -*-+-- vim: ft=haskell+{+module Language.Fortran.Parser.Free.Fortran95+ ( programParser+ , functionParser+ , blockParser+ , statementParser+ , expressionParser+ ) where++import Language.Fortran.Version+import Language.Fortran.Util.Position+import Language.Fortran.Parser.Monad+import Language.Fortran.Parser.Free.Lexer+import Language.Fortran.Parser.Free.Utils+import Language.Fortran.AST++import Prelude hiding ( EQ, LT, GT ) -- Same constructors exist in the AST+import Data.Either ( partitionEithers )++}++%name programParser PROGRAM+%name functionParser SUBPROGRAM_UNIT+%name blockParser BLOCK+%name statementParser STATEMENT+%name expressionParser EXPRESSION+%monad { LexAction }+%lexer { lexer } { TEOF _ }+%tokentype { Token }+%error { parseError }++%token+ id { TId _ _ }+ comment { TComment _ _ }+ string { TString _ _ }+ int { TIntegerLiteral _ _ }+ float { TRealLiteral _ _ }+ boz { TBozLiteral _ _ }+ '_' { TUnderscore _ }+ ',' { TComma _ }+ ',2' { TComma2 _ }+ ';' { TSemiColon _ }+ ':' { TColon _ }+ '::' { TDoubleColon _ }+ '=' { TOpAssign _ }+ '=>' { TArrow _ }+ '%' { TPercent _ }+ '(' { TLeftPar _ }+ '(2' { TLeftPar2 _ }+ ')' { TRightPar _ }+ '(/' { TLeftInitPar _ }+ '/)' { TRightInitPar _ }+ opCustom { TOpCustom _ _ }+ '**' { TOpExp _ }+ '+' { TOpPlus _ }+ '-' { TOpMinus _ }+ '*' { TStar _ }+ '/' { TOpDivision _ }+ slash { TSlash _ }+ or { TOpOr _ }+ and { TOpAnd _ }+ not { TOpNot _ }+ eqv { TOpEquivalent _ }+ neqv { TOpNotEquivalent _ }+ '<' { TOpLT _ }+ '<=' { TOpLE _ }+ '==' { TOpEQ _ }+ '!=' { TOpNE _ }+ '>' { TOpGT _ }+ '>=' { TOpGE _ }+ bool { TLogicalLiteral _ _ }+ program { TProgram _ }+ endProgram { TEndProgram _ }+ function { TFunction _ }+ endFunction { TEndFunction _ }+ result { TResult _ }+ pure { TPure _ }+ elemental { TElemental _ }+ recursive { TRecursive _ }+ subroutine { TSubroutine _ }+ endSubroutine { TEndSubroutine _ }+ blockData { TBlockData _ }+ endBlockData { TEndBlockData _ }+ module { TModule _ }+ endModule { TEndModule _ }+ contains { TContains _ }+ use { TUse _ }+ only { TOnly _ }+ interface { TInterface _ }+ endInterface { TEndInterface _ }+ moduleProcedure { TModuleProcedure _ }+ assignment { TAssignment _ }+ operator { TOperator _ }+ call { TCall _ }+ return { TReturn _ }+ entry { TEntry _ }+ include { TInclude _ }+ public { TPublic _ }+ private { TPrivate _ }+ parameter { TParameter _ }+ allocatable { TAllocatable _ }+ dimension { TDimension _ }+ external { TExternal _ }+ intent { TIntent _ }+ intrinsic { TIntrinsic _ }+ optional { TOptional _ }+ pointer { TPointer _ }+ save { TSave _ }+ target { TTarget _ }+ value { TValue _ }+ volatile { TVolatile _ }+ in { TIn _ }+ out { TOut _ }+ inout { TInOut _ }+ data { TData _ }+ namelist { TNamelist _ }+ implicit { TImplicit _ }+ equivalence { TEquivalence _ }+ common { TCommon _ }+ allocate { TAllocate _ }+ stat { TStat _ }+ deallocate { TDeallocate _ }+ nullify { TNullify _ }+ none { TNone _ }+ goto { TGoto _ }+ to { TTo _ }+ continue { TContinue _ }+ stop { TStop _ }+ do { TDo _ }+ enddo { TEndDo _ }+ while { TWhile _ }+ if { TIf _ }+ then { TThen _ }+ else { TElse _ }+ elsif { TElsif _ }+ endif { TEndIf _ }+ case { TCase _ }+ selectcase { TSelectCase _ }+ endselect { TEndSelect _ }+ default { TDefault _ }+ cycle { TCycle _ }+ exit { TExit _ }+ where { TWhere _ }+ elsewhere { TElsewhere _ }+ endwhere { TEndWhere _ }+ type { TType _ }+ endType { TEndType _ }+ sequence { TSequence _ }+ kind { TKind _ }+ len { TLen _ }+ integer { TInteger _ }+ real { TReal _ }+ doublePrecision { TDoublePrecision _ }+ logical { TLogical _ }+ character { TCharacter _ }+ complex { TComplex _ }+ open { TOpen _ }+ close { TClose _ }+ read { TRead _ }+ write { TWrite _ }+ print { TPrint _ }+ backspace { TBackspace _ }+ rewind { TRewind _ }+ inquire { TInquire _ }+ endfile { TEndfile _ }+ format { TFormat _ }+ blob { TBlob _ _ }+ end { TEnd _ }+ newline { TNewline _ }+ forall { TForall _ }+ endforall { TEndForall _ }+-- Precedence of operators++-- Level 6+%left opCustom++-- Level 5+%left eqv neqv+%left or+%left and+%right not++-- Level 4+%nonassoc '==' '!=' '>' '<' '>=' '<='+%nonassoc RELATIONAL++-- Level 3+%left CONCAT++-- Level 2+%left '+' '-'+%left '*' '/'+%right SIGN+%right '**'++-- Level 1+%right DEFINED_UNARY++-- Level 0+%left '%'++%%++maybe(p)+: p { Just $1 }+| {- empty -} { Nothing }++-- This rule is to ignore leading whitespace+PROGRAM :: { ProgramFile A0 }+: NEWLINE PROGRAM_INNER { $2 }+| PROGRAM_INNER { $1 }++PROGRAM_INNER :: { ProgramFile A0 }+: PROGRAM_UNITS { ProgramFile (MetaInfo { miVersion = Fortran95, miFilename = "" }) (reverse $1) }+| {- empty -} { ProgramFile (MetaInfo { miVersion = Fortran95, miFilename = "" }) [] }++PROGRAM_UNITS :: { [ ProgramUnit A0 ] }+: PROGRAM_UNITS PROGRAM_UNIT MAYBE_NEWLINE { $2 : $1 }+| PROGRAM_UNIT MAYBE_NEWLINE { [ $1 ] }++PROGRAM_UNIT :: { ProgramUnit A0 }+: program NAME NEWLINE BLOCKS MAYBE_SUBPROGRAM_UNITS PROGRAM_END+ {% do { unitNameCheck $6 $2;+ return $ PUMain () (getTransSpan $1 $6) (Just $2) (reverse $4) $5 } }+| module NAME NEWLINE BLOCKS MAYBE_SUBPROGRAM_UNITS MODULE_END+ {% do { unitNameCheck $6 $2;+ return $ PUModule () (getTransSpan $1 $6) $2 (reverse $4) $5 } }+| blockData NEWLINE BLOCKS BLOCK_DATA_END+ { PUBlockData () (getTransSpan $1 $4) Nothing (reverse $3) }+| blockData NAME NEWLINE BLOCKS BLOCK_DATA_END+ {% do { unitNameCheck $5 $2;+ return $ PUBlockData () (getTransSpan $1 $5) (Just $2) (reverse $4) } }+| SUBPROGRAM_UNIT { $1 }++MAYBE_SUBPROGRAM_UNITS :: { Maybe [ ProgramUnit A0 ] }+: contains NEWLINE SUBPROGRAM_UNITS { Just $ reverse $3 }+| {- Empty -} { Nothing }++SUBPROGRAM_UNITS :: { [ ProgramUnit A0 ] }+: SUBPROGRAM_UNITS SUBPROGRAM_UNIT NEWLINE { $2 : $1 }+| {- EMPTY -} { [ ] }++SUBPROGRAM_UNIT :: { ProgramUnit A0 }+: PREFIXES function NAME MAYBE_ARGUMENTS MAYBE_RESULT MAYBE_COMMENT NEWLINE BLOCKS MAYBE_SUBPROGRAM_UNITS FUNCTION_END+ {% do { unitNameCheck $10 $3;+ let (pfxs, typeSpec) = case partitionEithers $1 of+ { (ps, t:_) -> (fromReverseList' ps, Just t)+ ; (ps, []) -> (fromReverseList' ps, Nothing) } in+ let sfx = emptySuffixes in+ let ss = if null $1 then getTransSpan $2 $10 else getTransSpan (reverse $1) $10 in+ if validPrefixSuffix (pfxs, sfx) then+ return $ PUFunction () ss typeSpec (pfxs, sfx) $3 $4 $5 (reverse $8) $9+ else fail "Cannot specify elemental along with recursive." } }+| PREFIXES subroutine NAME MAYBE_ARGUMENTS MAYBE_COMMENT NEWLINE BLOCKS MAYBE_SUBPROGRAM_UNITS SUBROUTINE_END+ {% do { unitNameCheck $9 $3;+ (pfxs, typeSpec) <- case partitionEithers $1 of+ { (ps, t:_) -> fail "Subroutines cannot have return types."+ ; (ps, []) -> return (fromReverseList' ps, Nothing) };+ let sfx = emptySuffixes in+ let ss = if null $1 then getTransSpan $2 $9 else getTransSpan (reverse $1) $9 in+ if validPrefixSuffix (pfxs, sfx) then+ return $ PUSubroutine () ss (pfxs, sfx) $3 $4 (reverse $7) $8+ else fail "Cannot specify elemental along with recursive." } }+| comment { let (TComment s c) = $1 in PUComment () s (Comment c) }++-- (Fortran2003) R1227, Fortran95 (...)+PREFIXES :: { [Either (Prefix A0) (TypeSpec A0)] }+: PREFIXES PREFIX { $2:$1 }+| {- EMPTY -} { [] }++-- (Fortran2003) R1228, Fortran95 (...)+PREFIX :: { Either (Prefix A0) (TypeSpec A0) }+: recursive { Left $ PfxRecursive () (getSpan $1) }+| elemental { Left $ PfxElemental () (getSpan $1) }+| pure { Left $ PfxPure () (getSpan $1) }+| TYPE_SPEC { Right $1 }++RESULT :: { Expression A0 }+: result '(' VARIABLE ')' { $3 }++MAYBE_RESULT :: { Maybe (Expression A0) }+: RESULT { Just $1 }+| {- empty -} { Nothing}++MAYBE_ARGUMENTS :: { Maybe (AList Expression A0) }+: '(' MAYBE_VARIABLES ')' { $2 }+| {- Nothing -} { Nothing }++PROGRAM_END :: { Token }+: end { $1 } | endProgram { $1 } | endProgram id { $2 }+MODULE_END :: { Token }+: end { $1 } | endModule { $1 } | endModule id { $2 }+FUNCTION_END :: { Token }+: end { $1 } | endFunction { $1 } | endFunction id { $2 }+SUBROUTINE_END :: { Token }+: end { $1 } | endSubroutine { $1 } | endSubroutine id { $2 }+BLOCK_DATA_END :: { Token }+: end { $1 } | endBlockData { $1 } | endBlockData id { $2 }+INTERFACE_END :: { Token }+: end { $1 } | endInterface { $1 } | endInterface id { $2 }++NAME :: { Name } : id { let (TId _ name) = $1 in name }++BLOCKS :: { [ Block A0 ] } : BLOCKS BLOCK { $2 : $1 } | {- EMPTY -} { [ ] }++BLOCK :: { Block A0 }+: IF_BLOCK MAYBE_COMMENT NEWLINE { $1 }+| CASE_BLOCK MAYBE_COMMENT NEWLINE { $1 }+| INTEGER_LITERAL STATEMENT MAYBE_COMMENT NEWLINE+ { BlStatement () (getTransSpan $1 $2) (Just $1) $2 }+| STATEMENT MAYBE_COMMENT NEWLINE { BlStatement () (getSpan $1) Nothing $1 }+| interface MAYBE_EXPRESSION MAYBE_COMMENT NEWLINE SUBPROGRAM_UNITS2 MODULE_PROCEDURES INTERFACE_END MAYBE_COMMENT NEWLINE+ { BlInterface () (getTransSpan $1 $9) $2 False (reverse $5) (reverse $6) }+| interface MAYBE_EXPRESSION MAYBE_COMMENT NEWLINE MODULE_PROCEDURES INTERFACE_END MAYBE_COMMENT NEWLINE+ { BlInterface () (getTransSpan $1 $8) $2 False [ ] (reverse $5) }+| COMMENT_BLOCK { $1 }++IF_BLOCK :: { Block A0 }+IF_BLOCK+: if '(' EXPRESSION ')' then MAYBE_COMMENT NEWLINE BLOCKS ELSE_BLOCKS+ { let { startSpan = getSpan $1;+ (endSpan, conds, blocks, endLabel) = $9;+ span = getTransSpan startSpan endSpan }+ in BlIf () span Nothing Nothing ((Just $3):conds) ((reverse $8):blocks) endLabel }+| id ':' if '(' EXPRESSION ')' then MAYBE_COMMENT NEWLINE BLOCKS ELSE_BLOCKS+ { let { TId startSpan startName = $1;+ (endSpan, conds, blocks, endLabel) = $11;+ span = getTransSpan startSpan endSpan }+ in BlIf () span Nothing (Just startName) ((Just $5):conds) ((reverse $10):blocks) endLabel }+| INTEGER_LITERAL if '(' EXPRESSION ')' then MAYBE_COMMENT NEWLINE BLOCKS ELSE_BLOCKS+ { let { startSpan = getSpan $1;+ startLabel = Just $1;+ (endSpan, conds, blocks, endLabel) = $10;+ span = getTransSpan startSpan endSpan }+ in BlIf () span startLabel Nothing ((Just $4):conds) ((reverse $9):blocks) endLabel }+| INTEGER_LITERAL id ':' if '(' EXPRESSION ')' then MAYBE_COMMENT NEWLINE BLOCKS ELSE_BLOCKS+ { let { startSpan = getSpan $1;+ startLabel = Just $1;+ TId _ startName = $2;+ (endSpan, conds, blocks, endLabel) = $12;+ span = getTransSpan startSpan endSpan }+ in BlIf () span startLabel (Just startName) ((Just $6):conds) ((reverse $11):blocks) endLabel }++ELSE_BLOCKS :: { (SrcSpan, [Maybe (Expression A0)], [[Block A0]], Maybe (Expression A0)) }+ELSE_BLOCKS+: maybe(INTEGER_LITERAL) elsif '(' EXPRESSION ')' then MAYBE_COMMENT NEWLINE BLOCKS ELSE_BLOCKS+ { let (endSpan, conds, blocks, endLabel) = $10+ in (endSpan, Just $4 : conds, reverse $9 : blocks, endLabel) }+| maybe(INTEGER_LITERAL) else MAYBE_COMMENT NEWLINE BLOCKS END_IF+ { let (endSpan, endLabel) = $6+ in (endSpan, [Nothing], [reverse $5], endLabel) }+| END_IF { let (endSpan, endLabel) = $1 in (endSpan, [], [], endLabel) }++END_IF :: { (SrcSpan, Maybe (Expression A0)) }+END_IF+: endif { (getSpan $1, Nothing) }+| endif id { (getSpan $2, Nothing) }+| INTEGER_LITERAL endif { (getSpan $2, Just $1) }+| INTEGER_LITERAL endif id { (getSpan $3, Just $1) }++CASE_BLOCK :: { Block A0 }+CASE_BLOCK+: selectcase '(' EXPRESSION ')' MAYBE_COMMENT NEWLINE CASES+ { let { (caseRanges, blocks, endLabel, endSpan) = $7;+ span = getTransSpan $1 endSpan }+ in BlCase () span Nothing Nothing $3 caseRanges blocks endLabel }+| INTEGER_LITERAL selectcase '(' EXPRESSION ')' MAYBE_COMMENT NEWLINE CASES+ { let { (caseRanges, blocks, endLabel, endSpan) = $8;+ span = getTransSpan $1 endSpan }+ in BlCase () span (Just $1) Nothing $4 caseRanges blocks endLabel }+| id ':' selectcase '(' EXPRESSION ')' MAYBE_COMMENT NEWLINE CASES+ { let { (caseRanges, blocks, endLabel, endSpan) = $9;+ TId s startName = $1;+ span = getTransSpan s endSpan }+ in BlCase () span Nothing (Just startName) $5 caseRanges blocks endLabel }+| INTEGER_LITERAL id ':' selectcase '(' EXPRESSION ')' MAYBE_COMMENT NEWLINE CASES+ { let { (caseRanges, blocks, endLabel, endSpan) = $10;+ TId s startName = $2;+ span = getTransSpan s endSpan }+ in BlCase () span (Just $1) (Just startName) $6 caseRanges blocks endLabel }++-- We store line comments as statements, but this raises an issue: we have+-- nowhere to place comments after a SELECT CASE but before a CASE. So we drop+-- them. The inner CASES_ rule does /not/ use this, because comments can always+-- be parsed as belonging to to the above CASE block.+CASES :: { ([Maybe (AList Index A0)], [[Block A0]], Maybe (Expression A0), SrcSpan) }+: COMMENT_BLOCK CASES_ { $2 }+| CASES_ { $1 }++CASES_ :: { ([Maybe (AList Index A0)], [[Block A0]], Maybe (Expression A0), SrcSpan) }+: maybe(INTEGER_LITERAL) case '(' INDICIES ')' MAYBE_COMMENT NEWLINE BLOCKS CASES_+ { let (scrutinees, blocks, endLabel, endSpan) = $9+ in (Just (fromReverseList $4) : scrutinees, reverse $8 : blocks, endLabel, endSpan) }+| maybe(INTEGER_LITERAL) case default MAYBE_COMMENT NEWLINE BLOCKS END_SELECT+ { let (endLabel, endSpan) = $7+ in ([Nothing], [$6], endLabel, endSpan) }+| END_SELECT+ { let (endLabel, endSpan) = $1+ in ([], [], endLabel, endSpan) }++END_SELECT :: { (Maybe (Expression A0), SrcSpan) }+: maybe(INTEGER_LITERAL) endselect maybe(id)+ { ($1, maybe (getSpan $2) getSpan $3) }++MAYBE_EXPRESSION :: { Maybe (Expression A0) }+: EXPRESSION { Just $1 }+| {- EMPTY -} { Nothing }++MAYBE_COMMENT :: { Maybe Token }+: comment { Just $1 }+| {- EMPTY -} { Nothing }++SUBPROGRAM_UNITS2 :: { [ ProgramUnit A0 ] }+: SUBPROGRAM_UNITS SUBPROGRAM_UNIT NEWLINE { $2 : $1 }++MODULE_PROCEDURES :: { [ Block A0 ] }+: MODULE_PROCEDURES MODULE_PROCEDURE { $2 : $1 }+| MODULE_PROCEDURES MODULE_PROCEDURE COMMENT_BLOCK { $3 : $2 : $1 }+| { [ ] }++MODULE_PROCEDURE :: { Block A0 }+: moduleProcedure VARIABLES MAYBE_COMMENT NEWLINE+ { let { al = fromReverseList $2;+ st = StModuleProcedure () (getTransSpan $1 al) (fromReverseList $2) }+ in BlStatement () (getTransSpan $1 $4) Nothing st }++COMMENT_BLOCK :: { Block A0 }+: comment NEWLINE { let (TComment s c) = $1 in BlComment () s (Comment c) }++MAYBE_NEWLINE :: { Maybe Token } : NEWLINE { Just $1 } | {- EMPTY -} { Nothing }++NEWLINE :: { Token }+: NEWLINE newline { $1 }+| NEWLINE ';' { $1 }+| newline { $1 }+| ';' { $1 }++STATEMENT :: { Statement A0 }+: NONEXECUTABLE_STATEMENT { $1 }+| EXECUTABLE_STATEMENT { $1 }++EXPRESSION_ASSIGNMENT_STATEMENT :: { Statement A0 }+: DATA_REF '=' EXPRESSION { StExpressionAssign () (getTransSpan $1 $3) $1 $3 }++NONEXECUTABLE_STATEMENT :: { Statement A0 }+: DECLARATION_STATEMENT { $1 }+| intent '(' INTENT_CHOICE ')' MAYBE_DCOLON EXPRESSION_LIST+ { let expAList = fromReverseList $6+ in StIntent () (getTransSpan $1 expAList) $3 expAList }+| optional MAYBE_DCOLON EXPRESSION_LIST+ { let expAList = fromReverseList $3+ in StOptional () (getTransSpan $1 expAList) expAList }+| public MAYBE_DCOLON EXPRESSION_LIST+ { let expAList = fromReverseList $3+ in StPublic () (getTransSpan $1 expAList) (Just expAList) }+| public { StPublic () (getSpan $1) Nothing }+| private MAYBE_DCOLON EXPRESSION_LIST+ { let expAList = fromReverseList $3+ in StPrivate () (getTransSpan $1 expAList) (Just expAList) }+| private { StPrivate () (getSpan $1) Nothing }+| save MAYBE_DCOLON SAVE_ARGS+ { let saveAList = (fromReverseList $3)+ in StSave () (getTransSpan $1 saveAList) (Just saveAList) }+| save { StSave () (getSpan $1) Nothing }+| dimension MAYBE_DCOLON INITIALIZED_DECLARATOR_LIST+ { let declAList = fromReverseList $3+ in StDimension () (getTransSpan $1 declAList) declAList }+| allocatable MAYBE_DCOLON INITIALIZED_DECLARATOR_LIST+ { let declAList = fromReverseList $3+ in StAllocatable () (getTransSpan $1 declAList) declAList }+| pointer MAYBE_DCOLON INITIALIZED_DECLARATOR_LIST+ { let declAList = fromReverseList $3+ in StPointer () (getTransSpan $1 declAList) declAList }+| target MAYBE_DCOLON INITIALIZED_DECLARATOR_LIST+ { let declAList = fromReverseList $3+ in StTarget () (getTransSpan $1 declAList) declAList }+| value MAYBE_DCOLON INITIALIZED_DECLARATOR_LIST+ { let declAList = fromReverseList $3+ in StValue () (getTransSpan $1 declAList) declAList }+| volatile MAYBE_DCOLON INITIALIZED_DECLARATOR_LIST+ { let declAList = fromReverseList $3+ in StVolatile () (getTransSpan $1 declAList) declAList }+| data cDATA DATA_GROUPS cPOP+ { let dataAList = fromReverseList $3+ in StData () (getTransSpan $1 dataAList) dataAList }+| parameter '(' PARAMETER_ASSIGNMENTS ')'+ { let declAList = fromReverseList $3+ in StParameter () (getTransSpan $1 $4) declAList }+| implicit none { StImplicit () (getTransSpan $1 $2) Nothing }+| implicit cIMPLICIT IMP_LISTS cPOP+ { let impAList = fromReverseList $3+ in StImplicit () (getTransSpan $1 impAList) $ Just $ impAList }+| namelist cNAMELIST NAMELISTS cPOP+ { let nameALists = fromReverseList $3+ in StNamelist () (getTransSpan $1 nameALists) nameALists }+| equivalence EQUIVALENCE_GROUPS+ { let eqALists = fromReverseList $2+ in StEquivalence () (getTransSpan $1 eqALists) eqALists }+| common cCOMMON COMMON_GROUPS cPOP+ { let commonAList = fromReverseList $3+ in StCommon () (getTransSpan $1 commonAList) commonAList }+| external MAYBE_DCOLON VARIABLES+ { let alist = fromReverseList $3+ in StExternal () (getTransSpan $1 alist) alist }+| intrinsic MAYBE_DCOLON VARIABLES+ { let alist = fromReverseList $3+ in StIntrinsic () (getTransSpan $1 alist) alist }+| use VARIABLE { StUse () (getTransSpan $1 $2) $2 Nothing Permissive Nothing }+| use VARIABLE ',' RENAME_LIST+ { let alist = fromReverseList $4+ in StUse () (getTransSpan $1 alist) $2 Nothing Permissive (Just alist) }+| use VARIABLE ',' only ':' MAYBE_RENAME_LIST+ { StUse () (getTransSpan $1 ($5, $6)) $2 Nothing Exclusive $6 }+| entry VARIABLE MAYBE_RESULT+ { StEntry () (getTransSpan $1 $ maybe (getSpan $2) getSpan $3) $2 Nothing $3 }+| entry VARIABLE '(' ')' MAYBE_RESULT+ { StEntry () (getTransSpan $1 $ maybe (getSpan $4) getSpan $5) $2 Nothing $5 }+| entry VARIABLE '(' VARIABLES ')' MAYBE_RESULT+ { StEntry () (getTransSpan $1 $ maybe (getSpan $5) getSpan $6) $2 (Just $ fromReverseList $4) $6 }+| sequence { StSequence () (getSpan $1) }+| type ATTRIBUTE_LIST '::' id+ { let { TId span id = $4;+ alist = if null $2 then Nothing else (Just . fromReverseList) $2 }+ in StType () (getTransSpan $1 span) alist id }+| type id+ { let TId span id = $2 in StType () (getTransSpan $1 span) Nothing id }+| endType { StEndType () (getSpan $1) Nothing }+| endType id+ { let TId span id = $2 in StEndType () (getTransSpan $1 span) (Just id) }+| include STRING { StInclude () (getTransSpan $1 $2) $2 Nothing }+-- Following is a fake node to make arbitrary FORMAT statements parsable.+-- Must be fixed in the future. TODO+| format blob+ { let TBlob s blob = $2 in StFormatBogus () (getTransSpan $1 s) blob }++EXECUTABLE_STATEMENT :: { Statement A0 }+: allocate '(' DATA_REFS MAYBE_ALLOC_OPT_LIST ')'+ { StAllocate () (getTransSpan $1 $5) Nothing (fromReverseList $3) $4 }+| nullify '(' DATA_REFS ')'+ { StNullify () (getTransSpan $1 $4) (fromReverseList $3) }+| deallocate '(' DATA_REFS MAYBE_ALLOC_OPT_LIST ')'+ { StDeallocate () (getTransSpan $1 $5) (fromReverseList $3) $4 }+| EXPRESSION_ASSIGNMENT_STATEMENT { $1 }+| POINTER_ASSIGNMENT_STMT { $1 }+| where '(' EXPRESSION ')' EXPRESSION_ASSIGNMENT_STATEMENT+ { StWhere () (getTransSpan $1 $5) $3 $5 }+| where '(' EXPRESSION ')' { StWhereConstruct () (getTransSpan $1 $4) Nothing $3 }+| elsewhere '(' EXPRESSION ')' { StElsewhere () (getTransSpan $1 $4) Nothing (Just $3) }+| elsewhere { StElsewhere () (getSpan $1) Nothing Nothing }+| endwhere { StEndWhere () (getSpan $1) Nothing }+| if '(' EXPRESSION ')' INTEGER_LITERAL ',' INTEGER_LITERAL ',' INTEGER_LITERAL+ { StIfArithmetic () (getTransSpan $1 $9) $3 $5 $7 $9 }+| do { StDo () (getSpan $1) Nothing Nothing Nothing }+| id ':' do+ { let TId s id = $1+ in StDo () (getTransSpan s $3) (Just id) Nothing Nothing }+| do INTEGER_LITERAL MAYBE_COMMA DO_SPECIFICATION+ { StDo () (getTransSpan $1 $4) Nothing (Just $2) (Just $4) }+| do DO_SPECIFICATION { StDo () (getTransSpan $1 $2) Nothing Nothing (Just $2) }+| id ':' do DO_SPECIFICATION+ { let TId s id = $1+ in StDo () (getTransSpan s $4) (Just id) Nothing (Just $4) }+| do INTEGER_LITERAL MAYBE_COMMA while '(' EXPRESSION ')'+ { StDoWhile () (getTransSpan $1 $7) Nothing (Just $2) $6 }+| do while '(' EXPRESSION ')'+ { StDoWhile () (getTransSpan $1 $5) Nothing Nothing $4 }+| id ':' do while '(' EXPRESSION ')'+ { let TId s id = $1+ in StDoWhile () (getTransSpan s $7) (Just id) Nothing $6 }+| enddo { StEnddo () (getSpan $1) Nothing }+| enddo id+ { let TId s id = $2 in StEnddo () (getTransSpan $1 s) (Just id) }+| cycle { StCycle () (getSpan $1) Nothing }+| cycle VARIABLE { StCycle () (getTransSpan $1 $2) (Just $2) }+| exit { StExit () (getSpan $1) Nothing }+| exit VARIABLE { StExit () (getTransSpan $1 $2) (Just $2) }+-- GO TO label+| goto INTEGER_LITERAL { StGotoUnconditional () (getTransSpan $1 $2) $2 }+-- GO TO label-list [,] scalar-int-expression+| goto '(' INTEGERS ')' MAYBE_COMMA EXPRESSION+ { StGotoComputed () (getTransSpan $1 $6) (fromReverseList $3) $6 }+| continue { StContinue () (getSpan $1) }+| stop { StStop () (getSpan $1) Nothing }+| stop EXPRESSION { StStop () (getTransSpan $1 $2) (Just $2) }+| if '(' EXPRESSION ')' EXECUTABLE_STATEMENT+ { StIfLogical () (getTransSpan $1 $5) $3 $5 }+| read CILIST IN_IOLIST+ { let alist = fromReverseList $3+ in StRead () (getTransSpan $1 alist) $2 (Just alist) }+| read CILIST { StRead () (getTransSpan $1 $2) $2 Nothing }+| read FORMAT_ID ',' IN_IOLIST+ { let alist = fromReverseList $4+ in StRead2 () (getTransSpan $1 alist) $2 (Just alist) }+| read FORMAT_ID { StRead2 () (getTransSpan $1 $2) $2 Nothing }+| write CILIST OUT_IOLIST+ { let alist = fromReverseList $3+ in StWrite () (getTransSpan $1 alist) $2 (Just alist) }+| write CILIST { StWrite () (getTransSpan $1 $2) $2 Nothing }+| print FORMAT_ID ',' OUT_IOLIST+ { let alist = fromReverseList $4+ in StPrint () (getTransSpan $1 alist) $2 (Just alist) }+| print FORMAT_ID { StPrint () (getTransSpan $1 $2) $2 Nothing }+| open CILIST { StOpen () (getTransSpan $1 $2) $2 }+| close CILIST { StClose () (getTransSpan $1 $2) $2 }+| inquire CILIST { StInquire () (getTransSpan $1 $2) $2 }+| rewind CILIST { StRewind () (getTransSpan $1 $2) $2 }+| rewind UNIT { StRewind2 () (getTransSpan $1 $2) $2 }+| endfile CILIST { StEndfile () (getTransSpan $1 $2) $2 }+| endfile UNIT { StEndfile2 () (getTransSpan $1 $2) $2 }+| backspace CILIST { StBackspace () (getTransSpan $1 $2) $2 }+| backspace UNIT { StBackspace2 () (getTransSpan $1 $2) $2 }+| call VARIABLE { StCall () (getTransSpan $1 $2) $2 Nothing }+| call VARIABLE '(' ')' { StCall () (getTransSpan $1 $4) $2 Nothing }+| call VARIABLE '(' ARGUMENTS ')'+ { let alist = fromReverseList $4+ in StCall () (getTransSpan $1 $5) $2 (Just alist) }+| return { StReturn () (getSpan $1) Nothing }+| return EXPRESSION { StReturn () (getTransSpan $1 $2) (Just $2) }+| FORALL { $1 }+| END_FORALL { $1 }++ARGUMENTS :: { [ Argument A0 ] }+: ARGUMENTS ',' ARGUMENT { $3 : $1 }+| ARGUMENT { [ $1 ] }++ARGUMENT :: { Argument A0 }+: id '=' EXPRESSION+ { let TId span keyword = $1+ in Argument () (getTransSpan span $3) (Just keyword) (ArgExpr $3) }+| '(' VARIABLE ')'+ { let ExpValue _ _ (ValVariable v) = $2+ in Argument () (getTransSpan $1 $3) Nothing (ArgExprVar () (getSpan $2) v) }+| EXPRESSION+ { Argument () (getSpan $1) Nothing (ArgExpr $1) }++MAYBE_RENAME_LIST :: { Maybe (AList Use A0) }+: RENAME_LIST { Just $ fromReverseList $1 }+| {- empty -} { Nothing }++RENAME_LIST :: { [ Use A0 ] }+: RENAME_LIST ',' RENAME { $3 : $1 }+| RENAME { [ $1 ] }++RENAME :: { Use A0 }+: VARIABLE '=>' VARIABLE { UseRename () (getTransSpan $1 $3) $1 $3 }+| VARIABLE { UseID () (getSpan $1) $1 }+| operator '(' opCustom ')'+ { let TOpCustom ss op = $3+ in UseID () (getTransSpan $1 $4) (ExpValue () ss (ValOperator op)) }+| assignment { UseID () (getSpan $1) (ExpValue () (getSpan $1) ValAssignment) }++MAYBE_DCOLON :: { () } : '::' { () } | {- EMPTY -} { () }++FORMAT_ID :: { Expression A0 }+: FORMAT_ID '/' '/' FORMAT_ID %prec CONCAT+ { ExpBinary () (getTransSpan $1 $4) Concatenation $1 $4 }+| INTEGER_LITERAL { $1 }+| STRING { $1 }+| DATA_REF { $1 }+| '*' { ExpValue () (getSpan $1) ValStar }++UNIT :: { Expression A0 }+: INTEGER_LITERAL { $1 }+| DATA_REF { $1 }+| '*' { ExpValue () (getSpan $1) ValStar }++CILIST :: { AList ControlPair A0 }+: '(' CILIST_ELEMENT ',' FORMAT_ID ',' CILIST_PAIRS ')'+ { let { cp1 = ControlPair () (getSpan $2) Nothing $2;+ cp2 = ControlPair () (getSpan $4) Nothing $4;+ tail = fromReverseList $6 }+ in setSpan (getTransSpan $1 $7) $ cp1 `aCons` cp2 `aCons` tail }+| '(' CILIST_ELEMENT ',' FORMAT_ID ')'+ { let { cp1 = ControlPair () (getSpan $2) Nothing $2;+ cp2 = ControlPair () (getSpan $4) Nothing $4 }+ in AList () (getTransSpan $1 $5) [ cp1, cp2 ] }+| '(' CILIST_ELEMENT ',' CILIST_PAIRS ')'+ { let { cp1 = ControlPair () (getSpan $2) Nothing $2;+ tail = fromReverseList $4 }+ in setSpan (getTransSpan $1 $5) $ cp1 `aCons` tail }+| '(' CILIST_ELEMENT ')'+ { let cp1 = ControlPair () (getSpan $2) Nothing $2+ in AList () (getTransSpan $1 $3) [ cp1 ] }+| '(' CILIST_PAIRS ')' { fromReverseList $2 }++CILIST_PAIRS :: { [ ControlPair A0 ] }+: CILIST_PAIRS ',' CILIST_PAIR { $3 : $1 }+| CILIST_PAIR { [ $1 ] }++CILIST_PAIR :: { ControlPair A0 }+: id '=' CILIST_ELEMENT+ { let (TId s id) = $1 in ControlPair () (getTransSpan s $3) (Just id) $3 }++CILIST_ELEMENT :: { Expression A0 }+: CI_EXPRESSION { $1 }+| '*' { ExpValue () (getSpan $1) ValStar }++CI_EXPRESSION :: { Expression A0 }+: CI_EXPRESSION '+' CI_EXPRESSION+ { ExpBinary () (getTransSpan $1 $3) Addition $1 $3 }+| CI_EXPRESSION '-' CI_EXPRESSION+ { ExpBinary () (getTransSpan $1 $3) Subtraction $1 $3 }+| CI_EXPRESSION '*' CI_EXPRESSION+ { ExpBinary () (getTransSpan $1 $3) Multiplication $1 $3 }+| CI_EXPRESSION '/' CI_EXPRESSION+ { ExpBinary () (getTransSpan $1 $3) Division $1 $3 }+| CI_EXPRESSION '**' CI_EXPRESSION+ { ExpBinary () (getTransSpan $1 $3) Exponentiation $1 $3 }+| CI_EXPRESSION '/' '/' CI_EXPRESSION %prec CONCAT+ { ExpBinary () (getTransSpan $1 $4) Concatenation $1 $4 }+| ARITHMETIC_SIGN CI_EXPRESSION %prec SIGN+ { ExpUnary () (getTransSpan (fst $1) $2) (snd $1) $2 }+| CI_EXPRESSION or CI_EXPRESSION+ { ExpBinary () (getTransSpan $1 $3) Or $1 $3 }+| CI_EXPRESSION and CI_EXPRESSION+ { ExpBinary () (getTransSpan $1 $3) And $1 $3 }+| not CI_EXPRESSION+ { ExpUnary () (getTransSpan $1 $2) Not $2 }+| CI_EXPRESSION eqv CI_EXPRESSION+ { ExpBinary () (getTransSpan $1 $3) Equivalent $1 $3 }+| CI_EXPRESSION neqv CI_EXPRESSION+ { ExpBinary () (getTransSpan $1 $3) NotEquivalent $1 $3 }+| CI_EXPRESSION RELATIONAL_OPERATOR CI_EXPRESSION %prec RELATIONAL+ { ExpBinary () (getTransSpan $1 $3) $2 $1 $3 }+| opCustom CI_EXPRESSION %prec DEFINED_UNARY+ { let TOpCustom span str = $1+ in ExpUnary () (getTransSpan span $2) (UnCustom str) $2 }+| CI_EXPRESSION opCustom CI_EXPRESSION+ { let TOpCustom _ str = $2+ in ExpBinary () (getTransSpan $1 $3) (BinCustom str) $1 $3 }+| '(' CI_EXPRESSION ')' { setSpan (getTransSpan $1 $3) $2 }+| INTEGER_LITERAL { $1 }+| LOGICAL_LITERAL { $1 }+| STRING { $1 }+| DATA_REF { $1 }++{- p67 ALLOCATE statement -}+MAYBE_ALLOC_OPT_LIST :: { Maybe (AList AllocOpt A0) }+: ',' stat '=' EXPRESSION { Just (fromReverseList [AOStat () (getTransSpan $2 $4) $4]) }+| {- empty -} { Nothing }++IN_IOLIST :: { [ Expression A0 ] }+: IN_IOLIST ',' IN_IO_ELEMENT { $3 : $1}+| IN_IO_ELEMENT { [ $1 ] }++IN_IO_ELEMENT :: { Expression A0 }+: DATA_REF { $1 }+| '(' IN_IOLIST ',' DO_SPECIFICATION ')'+ { ExpImpliedDo () (getTransSpan $1 $5) (fromReverseList $2) $4 }++OUT_IOLIST :: { [ Expression A0 ] }+: OUT_IOLIST ',' EXPRESSION { $3 : $1}+| EXPRESSION { [ $1 ] }++COMMON_GROUPS :: { [ CommonGroup A0 ] }+: COMMON_GROUPS COMMON_GROUP { $2 : $1 }+| COMMON_GROUPS ',2' COMMON_GROUP { $3 : $1 }+| INIT_COMMON_GROUP { [ $1 ] }++COMMON_GROUP :: { CommonGroup A0 }+: COMMON_NAME UNINITIALIZED_DECLARATOR_LIST+ { let alist = fromReverseList $2+ in CommonGroup () (getTransSpan $1 alist) (Just $1) alist }+| '/' '/' UNINITIALIZED_DECLARATOR_LIST+ { let alist = fromReverseList $3+ in CommonGroup () (getTransSpan $1 alist) Nothing alist }++INIT_COMMON_GROUP :: { CommonGroup A0 }+: COMMON_NAME UNINITIALIZED_DECLARATOR_LIST+ { let alist = fromReverseList $2+ in CommonGroup () (getTransSpan $1 alist) (Just $1) alist }+| '/' '/' UNINITIALIZED_DECLARATOR_LIST+ { let alist = fromReverseList $3+ in CommonGroup () (getTransSpan $1 alist) Nothing alist }+| UNINITIALIZED_DECLARATOR_LIST+ { let alist = fromReverseList $1+ in CommonGroup () (getSpan alist) Nothing alist }++EQUIVALENCE_GROUPS :: { [ AList Expression A0 ] }+: EQUIVALENCE_GROUPS ',' '(' PART_REFS ')'+ { setSpan (getTransSpan $3 $5) (fromReverseList $4) : $1 }+| '(' PART_REFS ')'+ { [ setSpan (getTransSpan $1 $3) (fromReverseList $2) ] }++NAMELISTS :: { [ Namelist A0 ] }+: NAMELISTS NAMELIST { $2 : $1 }+| NAMELISTS ',2' NAMELIST { $3 : $1 }+| NAMELIST { [ $1 ] }++NAMELIST :: { Namelist A0 }+: '/' VARIABLE '/' VARIABLES+ { Namelist () (getTransSpan $1 $4) $2 $ fromReverseList $4 }++MAYBE_VARIABLES :: { Maybe (AList Expression A0) }+: VARIABLES { Just $ fromReverseList $1 } | {- EMPTY -} { Nothing }++VARIABLES :: { [ Expression A0 ] }+: VARIABLES ',' VARIABLE { $3 : $1 }+| VARIABLE { [ $1 ] }++IMP_LISTS :: { [ ImpList A0 ] }+: IMP_LISTS ',' IMP_LIST { $3 : $1 }+| IMP_LIST { [ $1 ] }++IMP_LIST :: { ImpList A0 }+: TYPE_SPEC '(2' IMP_ELEMENTS ')'+ { ImpList () (getTransSpan $1 $4) $1 (aReverse $3) }++IMP_ELEMENTS :: { AList ImpElement A0 }+: IMP_ELEMENTS ',' IMP_ELEMENT { setSpan (getTransSpan $1 $3) $ $3 `aCons` $1 }+| IMP_ELEMENT { AList () (getSpan $1) [ $1 ] }++IMP_ELEMENT :: { ImpElement A0 }+: id {% do+ let (TId s id) = $1+ if length id /= 1+ then fail "Implicit argument must be a character."+ else return $ ImpCharacter () s id+ }+| id '-' id {% do+ let (TId _ id1) = $1+ let (TId _ id2) = $3+ if length id1 /= 1 || length id2 /= 1+ then fail "Implicit argument must be a character."+ else return $ ImpRange () (getTransSpan $1 $3) id1 id2+ }++PARAMETER_ASSIGNMENTS :: { [ Declarator A0 ] }+: PARAMETER_ASSIGNMENTS ',' PARAMETER_ASSIGNMENT { $3 : $1 }+| PARAMETER_ASSIGNMENT { [ $1 ] }++PARAMETER_ASSIGNMENT :: { Declarator A0 }+: VARIABLE '=' EXPRESSION+ { Declarator () (getTransSpan $1 $3) $1 ScalarDecl Nothing (Just $3) }++DECLARATION_STATEMENT :: { Statement A0 }+: TYPE_SPEC ATTRIBUTE_LIST '::' INITIALIZED_DECLARATOR_LIST+ { let { mAttrAList = if null $2 then Nothing else Just $ fromReverseList $2;+ declAList = fromReverseList $4 }+ in StDeclaration () (getTransSpan $1 declAList) $1 mAttrAList declAList }+| TYPE_SPEC INITIALIZED_DECLARATOR_LIST+ { let { declAList = fromReverseList $2 }+ in StDeclaration () (getTransSpan $1 declAList) $1 Nothing declAList }++ATTRIBUTE_LIST :: { [ Attribute A0 ] }+: ATTRIBUTE_LIST ',' ATTRIBUTE_SPEC { $3 : $1 }+| {- EMPTY -} { [ ] }++ATTRIBUTE_SPEC :: { Attribute A0 }+: public { AttrPublic () (getSpan $1) }+| private { AttrPrivate () (getSpan $1) }+| allocatable { AttrAllocatable () (getSpan $1) }+| dimension '(' DIMENSION_DECLARATORS ')'+ { AttrDimension () (getTransSpan $1 $4) (aReverse $3) }+| external { AttrExternal () (getSpan $1) }+| intent '(' INTENT_CHOICE ')' { AttrIntent () (getTransSpan $1 $4) $3 }+| intrinsic { AttrIntrinsic () (getSpan $1) }+| optional { AttrOptional () (getSpan $1) }+| pointer { AttrPointer () (getSpan $1) }+| parameter { AttrParameter () (getSpan $1) }+| save { AttrSave () (getSpan $1) }+| target { AttrTarget () (getSpan $1) }+| value { AttrValue () (getSpan $1) }+| volatile { AttrVolatile () (getSpan $1) }++INTENT_CHOICE :: { Intent } : in { In } | out { Out } | inout { InOut }++DATA_GROUPS :: { [ DataGroup A0 ] }+: DATA_GROUPS MAYBE_COMMA DATA_LIST slash EXPRESSION_LIST slash+ { let { nameAList = fromReverseList $3;+ dataAList = fromReverseList $5 }+ in DataGroup () (getTransSpan nameAList $6) nameAList dataAList : $1 }+| DATA_LIST slash EXPRESSION_LIST slash+ { let { nameAList = fromReverseList $1;+ dataAList = fromReverseList $3 }+ in [ DataGroup () (getTransSpan nameAList $4) nameAList dataAList ] }++MAYBE_COMMA :: { () } : ',' { () } | {- EMPTY -} { () }++DATA_LIST :: { [ Expression A0 ] }+: DATA_LIST ',' DATA_ELEMENT { $3 : $1 }+| DATA_ELEMENT { [ $1 ] }++DATA_ELEMENT :: { Expression A0 }+: DATA_REF { $1 } | IMPLIED_DO { $1 }++SAVE_ARGS :: { [ Expression A0 ] }+: SAVE_ARGS ',' SAVE_ARG { $3 : $1 } | SAVE_ARG { [ $1 ] }++SAVE_ARG :: { Expression A0 } : COMMON_NAME { $1 } | VARIABLE { $1 }++COMMON_NAME :: { Expression A0 }+: '/' VARIABLE '/' { setSpan (getTransSpan $1 $3) $2 }++INITIALIZED_DECLARATOR_LIST :: { [ Declarator A0 ] }+: INITIALIZED_DECLARATOR_LIST ',' INITIALIZED_DECLARATOR { $3 : $1 }+| INITIALIZED_DECLARATOR { [ $1 ] }++UNINITIALIZED_DECLARATOR_LIST :: { [ Declarator A0 ] }+: UNINITIALIZED_DECLARATOR_LIST ',' DECLARATOR { $3 : $1 }+| DECLARATOR { [ $1 ] }++INITIALIZED_DECLARATOR :: { Declarator A0 }+: DECLARATOR '=' EXPRESSION { setInitialisation $1 $3 }+| DECLARATOR '=>' EXPRESSION { setInitialisation $1 $3 }+| DECLARATOR { $1 }++DECLARATOR :: { Declarator A0 }+: VARIABLE+ { Declarator () (getSpan $1) $1 ScalarDecl Nothing Nothing }+| VARIABLE '*' EXPRESSION+ { Declarator () (getTransSpan $1 $3) $1 ScalarDecl (Just $3) Nothing }+| VARIABLE '*' '(' '*' ')'+ { let star = ExpValue () (getSpan $4) ValStar+ in Declarator () (getTransSpan $1 $5) $1 ScalarDecl (Just star) Nothing }+| VARIABLE '(' DIMENSION_DECLARATORS ')'+ { Declarator () (getTransSpan $1 $4) $1 (ArrayDecl (aReverse $3)) Nothing Nothing }+| VARIABLE '(' DIMENSION_DECLARATORS ')' '*' EXPRESSION+ { Declarator () (getTransSpan $1 $6) $1 (ArrayDecl (aReverse $3)) (Just $6) Nothing }+-- nonstandard char array syntax (wrong order for dimensions & charlen)+| VARIABLE '*' EXPRESSION '(' DIMENSION_DECLARATORS ')'+ { Declarator () (getTransSpan $1 $6) $1 (ArrayDecl (aReverse $5)) (Just $3) Nothing }+| VARIABLE '(' DIMENSION_DECLARATORS ')' '*' '(' '*' ')'+ { let star = ExpValue () (getSpan $7) ValStar+ in Declarator () (getTransSpan $1 $8) $1 (ArrayDecl (aReverse $3)) (Just star) Nothing }++DIMENSION_DECLARATORS :: { AList DimensionDeclarator A0 }+: DIMENSION_DECLARATORS ',' DIMENSION_DECLARATOR+ { setSpan (getTransSpan $1 $3) $ $3 `aCons` $1 }+| DIMENSION_DECLARATOR+ { AList () (getSpan $1) [ $1 ] }++DIMENSION_DECLARATOR :: { DimensionDeclarator A0 }+: EXPRESSION ':' EXPRESSION+ { DimensionDeclarator () (getTransSpan $1 $3) (Just $1) (Just $3) }+| EXPRESSION { DimensionDeclarator () (getSpan $1) Nothing (Just $1) }+-- Lower bound only+| EXPRESSION ':'+ { DimensionDeclarator () (getTransSpan $1 $2) (Just $1) Nothing }+| EXPRESSION ':' '*'+ { let { span = getSpan $3;+ star = ExpValue () span ValStar }+ in DimensionDeclarator () (getTransSpan $1 span) (Just $1) (Just star) }+| '*'+ { let { span = getSpan $1;+ star = ExpValue () span ValStar }+ in DimensionDeclarator () span Nothing (Just star) }+| ':'+ { let span = getSpan $1+ in DimensionDeclarator () span Nothing Nothing }++TYPE_SPEC :: { TypeSpec A0 }+: integer KIND_SELECTOR { TypeSpec () (getSpan ($1, $2)) TypeInteger $2 }+| real KIND_SELECTOR { TypeSpec () (getSpan ($1, $2)) TypeReal $2 }+| doublePrecision { TypeSpec () (getSpan $1) TypeDoublePrecision Nothing }+| complex KIND_SELECTOR { TypeSpec () (getSpan ($1, $2)) TypeComplex $2 }+| character CHAR_SELECTOR { TypeSpec () (getSpan ($1, $2)) TypeCharacter $2 }+| logical KIND_SELECTOR { TypeSpec () (getSpan ($1, $2)) TypeLogical $2 }+| type '(' id ')'+ { let TId _ id = $3+ in TypeSpec () (getTransSpan $1 $4) (TypeCustom id) Nothing }++KIND_SELECTOR :: { Maybe (Selector A0) }+: '(' EXPRESSION ')'+ { Just $ Selector () (getTransSpan $1 $3) Nothing (Just $2) }+| '(' kind '=' EXPRESSION ')'+ { Just $ Selector () (getTransSpan $1 $5) Nothing (Just $4) }+| '*' EXPRESSION -- non-standard but commonly used extension+ { Just $ Selector () (getTransSpan $1 $2) Nothing (Just $2) }+| {- EMPTY -} { Nothing }++CHAR_SELECTOR :: { Maybe (Selector A0) }+: '*' EXPRESSION+ { Just $ Selector () (getTransSpan $1 $2) (Just $2) Nothing }+-- The following rule is a bug in the spec.+-- | '*' EXPRESSION ','+-- { Just $ Selector () (getTransSpan $1 $2) (Just $2) Nothing }+| '*' '(' '*' ')'+ { let star = ExpValue () (getSpan $3) ValStar+ in Just $ Selector () (getTransSpan $1 $4) (Just star) Nothing }+| '(' LEN_EXPRESSION ')'+ { Just $ Selector () (getTransSpan $1 $3) (Just $2) Nothing }+| '(' len '=' LEN_EXPRESSION ')'+ { Just $ Selector () (getTransSpan $1 $5) (Just $4) Nothing }+| '(' kind '=' EXPRESSION ')'+ { Just $ Selector () (getTransSpan $1 $5) Nothing (Just $4) }+| '(' LEN_EXPRESSION ',' EXPRESSION ')'+ { Just $ Selector () (getTransSpan $1 $5) (Just $2) (Just $4) }+| '(' LEN_EXPRESSION ',' kind '=' EXPRESSION ')'+ { Just $ Selector () (getTransSpan $1 $7) (Just $2) (Just $6) }+| '(' len '=' LEN_EXPRESSION ',' kind '=' EXPRESSION ')'+ { Just $ Selector () (getTransSpan $1 $9) (Just $4) (Just $8) }+| '(' kind '=' EXPRESSION ',' len '=' LEN_EXPRESSION ')'+ { Just $ Selector () (getTransSpan $1 $9) (Just $8) (Just $4) }+| {- EMPTY -} { Nothing }++LEN_EXPRESSION :: { Expression A0 }+: EXPRESSION { $1 }+| '*' { ExpValue () (getSpan $1) ValStar }++EXPRESSION :: { Expression A0 }+: EXPRESSION '+' EXPRESSION+ { ExpBinary () (getTransSpan $1 $3) Addition $1 $3 }+| EXPRESSION '-' EXPRESSION+ { ExpBinary () (getTransSpan $1 $3) Subtraction $1 $3 }+| EXPRESSION '*' EXPRESSION+ { ExpBinary () (getTransSpan $1 $3) Multiplication $1 $3 }+| EXPRESSION '/' EXPRESSION+ { ExpBinary () (getTransSpan $1 $3) Division $1 $3 }+| EXPRESSION '**' EXPRESSION+ { ExpBinary () (getTransSpan $1 $3) Exponentiation $1 $3 }+| EXPRESSION '/' '/' EXPRESSION %prec CONCAT+ { ExpBinary () (getTransSpan $1 $4) Concatenation $1 $4 }+| ARITHMETIC_SIGN EXPRESSION %prec SIGN+ { ExpUnary () (getTransSpan (fst $1) $2) (snd $1) $2 }+| EXPRESSION or EXPRESSION+ { ExpBinary () (getTransSpan $1 $3) Or $1 $3 }+| EXPRESSION and EXPRESSION+ { ExpBinary () (getTransSpan $1 $3) And $1 $3 }+| not EXPRESSION+ { ExpUnary () (getTransSpan $1 $2) Not $2 }+| EXPRESSION eqv EXPRESSION+ { ExpBinary () (getTransSpan $1 $3) Equivalent $1 $3 }+| EXPRESSION neqv EXPRESSION+ { ExpBinary () (getTransSpan $1 $3) NotEquivalent $1 $3 }+| EXPRESSION RELATIONAL_OPERATOR EXPRESSION %prec RELATIONAL+ { ExpBinary () (getTransSpan $1 $3) $2 $1 $3 }+| opCustom EXPRESSION %prec DEFINED_UNARY+ { let TOpCustom span str = $1+ in ExpUnary () (getTransSpan span $2) (UnCustom str) $2 }+| EXPRESSION opCustom EXPRESSION+ { let TOpCustom _ str = $2+ in ExpBinary () (getTransSpan $1 $3) (BinCustom str) $1 $3 }+| '(' EXPRESSION ')' { setSpan (getTransSpan $1 $3) $2 }+| NUMERIC_LITERAL { $1 }+| '(' EXPRESSION ',' EXPRESSION ')'+ { ExpValue () (getTransSpan $1 $5) (ValComplex $2 $4) }+| LOGICAL_LITERAL { $1 }+| STRING { $1 }+| DATA_REF { $1 }+| IMPLIED_DO { $1 }+| '(/' EXPRESSION_LIST '/)'+ { ExpInitialisation () (getTransSpan $1 $3) (fromReverseList $2) }+| operator '(' opCustom ')'+ { let TOpCustom _ op = $3+ in ExpValue () (getTransSpan $1 $4) (ValOperator op) }+| assignment { ExpValue () (getSpan $1) ValAssignment }+| '*' INTEGER_LITERAL { ExpReturnSpec () (getTransSpan $1 $2) $2 }++DATA_REFS :: { [ Expression A0 ] }+: DATA_REFS ',' DATA_REF { $3 : $1 }+| DATA_REF { [ $1 ] }++DATA_REF :: { Expression A0 }+: DATA_REF '%' PART_REF { ExpDataRef () (getTransSpan $1 $3) $1 $3 }+| PART_REF { $1 }++PART_REFS :: { [ Expression A0 ] }+: PART_REFS ',' PART_REF { $3 : $1 }+| PART_REF { [ $1 ] }++PART_REF :: { Expression A0 }+: VARIABLE { $1 }+| VARIABLE '(' ')'+ { ExpFunctionCall () (getTransSpan $1 $3) $1 Nothing }+| VARIABLE '(' INDICIES ')'+ { ExpSubscript () (getTransSpan $1 $4) $1 (fromReverseList $3) }+| VARIABLE '(' INDICIES ')' '(' INDICIES ')'+ { let innerSub = ExpSubscript () (getTransSpan $1 $4) $1 (fromReverseList $3)+ in ExpSubscript () (getTransSpan $1 $7) innerSub (fromReverseList $6) }++INDICIES :: { [ Index A0 ] }+: INDICIES ',' INDEX { $3 : $1 }+| INDEX { [ $1 ] }++INDEX :: { Index A0 }+: RANGE { $1 }+| RANGE ':' EXPRESSION+ { let IxRange () s lower upper _ = $1+ in IxRange () (getTransSpan s $3) lower upper (Just $3) }+| EXPRESSION { IxSingle () (getSpan $1) Nothing $1 }+-- Following is only as an intermediate stage before having been turned into+-- an argument by later transformation.+| id '=' EXPRESSION+ { let TId s id = $1 in IxSingle () (getTransSpan $1 s) (Just id) $3 }++RANGE :: { Index A0 }+: ':' { IxRange () (getSpan $1) Nothing Nothing Nothing }+| ':' EXPRESSION { IxRange () (getTransSpan $1 $2) Nothing (Just $2) Nothing }+| EXPRESSION ':' { IxRange () (getTransSpan $1 $2) (Just $1) Nothing Nothing }+| EXPRESSION ':' EXPRESSION+ { IxRange () (getTransSpan $1 $3) (Just $1) (Just $3) Nothing }++DO_SPECIFICATION :: { DoSpecification A0 }+: EXPRESSION_ASSIGNMENT_STATEMENT ',' EXPRESSION ',' EXPRESSION+ { DoSpecification () (getTransSpan $1 $5) $1 $3 (Just $5) }+| EXPRESSION_ASSIGNMENT_STATEMENT ',' EXPRESSION+ { DoSpecification () (getTransSpan $1 $3) $1 $3 Nothing }++IMPLIED_DO :: { Expression A0 }+: '(' EXPRESSION ',' DO_SPECIFICATION ')'+ { let expList = AList () (getSpan $2) [ $2 ]+ in ExpImpliedDo () (getTransSpan $1 $5) expList $4 }+| '(' EXPRESSION ',' EXPRESSION ',' DO_SPECIFICATION ')'+ { let expList = AList () (getTransSpan $2 $4) [ $2, $4 ]+ in ExpImpliedDo () (getTransSpan $1 $5) expList $6 }+| '(' EXPRESSION ',' EXPRESSION ',' EXPRESSION_LIST ',' DO_SPECIFICATION ')'+ { let { exps = reverse $6;+ expList = AList () (getTransSpan $2 exps) ($2 : $4 : reverse $6) }+ in ExpImpliedDo () (getTransSpan $1 $9) expList $8 }++FORALL :: { Statement A0 }+: id ':' forall FORALL_HEADER {+ let (TId s1 id) = $1 in+ let (h,s2) = $4 in+ StForall () (getTransSpan s1 s2) (Just id) h+}+| forall FORALL_HEADER {+ let (h,s) = $2 in+ StForall () (getTransSpan $1 s) Nothing h+}+| forall FORALL_HEADER FORALL_ASSIGNMENT_STMT {+ let (h,_) = $2 in+ StForallStatement () (getTransSpan $1 $3) h $3+}++FORALL_HEADER+ :: { (ForallHeader A0, SrcSpan) }+FORALL_HEADER :+ -- Standard simple forall header+ '(' FORALL_TRIPLET_SPEC ')' { (ForallHeader [$2] Nothing, getTransSpan $1 $3) }+ -- forall header with scale expression+ | '(' '(' FORALL_TRIPLET_SPEC ')' ',' EXPRESSION ')'+ { (ForallHeader [$3] (Just $6), getTransSpan $1 $7) }+ -- multi forall header+ | '(' FORALL_TRIPLET_SPEC_LIST_PLUS_STRIDE ')'+ { (ForallHeader $2 Nothing, getTransSpan $1 $3) }+ -- multi forall header with scale+ | '(' FORALL_TRIPLET_SPEC_LIST_PLUS_STRIDE ',' EXPRESSION ')'+ { (ForallHeader $2 (Just $4), getTransSpan $1 $5) }++FORALL_TRIPLET_SPEC_LIST_PLUS_STRIDE+ :: { [(Name, Expression A0, Expression A0, Maybe (Expression A0))] }+FORALL_TRIPLET_SPEC_LIST_PLUS_STRIDE+: '(' FORALL_TRIPLET_SPEC ')' ',' FORALL_TRIPLET_SPEC_LIST_PLUS_STRIDE { $2 : $5 }+| {- empty -} { [] }++FORALL_TRIPLET_SPEC :: { (Name, Expression A0, Expression A0, Maybe (Expression A0)) }+FORALL_TRIPLET_SPEC+: NAME '=' EXPRESSION ':' EXPRESSION { ($1, $3, $5, Nothing) }+| NAME '=' EXPRESSION ':' EXPRESSION ',' EXPRESSION { ($1, $3, $5, Just $7) }++FORALL_ASSIGNMENT_STMT :: { Statement A0 }+FORALL_ASSIGNMENT_STMT :+ EXPRESSION_ASSIGNMENT_STATEMENT { $1 }+ | POINTER_ASSIGNMENT_STMT { $1 }++POINTER_ASSIGNMENT_STMT :: { Statement A0 }+POINTER_ASSIGNMENT_STMT :+ DATA_REF '=>' EXPRESSION { StPointerAssign () (getTransSpan $1 $3) $1 $3 }++END_FORALL :: { Statement A0 }+END_FORALL :+ endforall { StEndForall () (getSpan $1) Nothing }+ | endforall id { let (TId s id) = $2 in StEndForall () (getTransSpan $1 s) (Just id)}++EXPRESSION_LIST :: { [ Expression A0 ] }+: EXPRESSION_LIST ',' EXPRESSION { $3 : $1 }+| EXPRESSION { [ $1 ] }++ARITHMETIC_SIGN :: { (SrcSpan, UnaryOp) }+: '-' { (getSpan $1, Minus) }+| '+' { (getSpan $1, Plus) }++RELATIONAL_OPERATOR :: { BinaryOp }+: '==' { EQ }+| '!=' { NE }+| '>' { GT }+| '>=' { GTE }+| '<' { LT }+| '<=' { LTE }++VARIABLE :: { Expression A0 }+: id { ExpValue () (getSpan $1) $ let (TId _ s) = $1 in ValVariable s }++NUMERIC_LITERAL :: { Expression A0 }+: INTEGER_LITERAL { $1 } | REAL_LITERAL { $1 }++INTEGERS :: { [ Expression A0 ] }+: INTEGERS ',' INTEGER_LITERAL { $3 : $1 }+| INTEGER_LITERAL { [ $1 ] }++INTEGER_LITERAL :: { Expression A0 }+: int+ { let TIntegerLiteral s i = $1+ in ExpValue () s $ ValInteger i Nothing }+| int '_' KIND_PARAM+ { let TIntegerLiteral s i = $1+ in ExpValue () s $ ValInteger i (Just $3) }+| boz { let TBozLiteral s b = $1 in ExpValue () s $ ValBoz b }++REAL_LITERAL :: { Expression A0 }+: float+ { let TRealLiteral s r = $1+ in ExpValue () s $ ValReal r Nothing }+| float '_' KIND_PARAM+ { let TRealLiteral s r = $1+ in ExpValue () s $ ValReal r (Just $3) }++LOGICAL_LITERAL :: { Expression A0 }+: bool+ { let TLogicalLiteral s b = $1+ in ExpValue () s (ValLogical b Nothing) }+| bool '_' KIND_PARAM+ { let TLogicalLiteral s b = $1+ in ExpValue () s (ValLogical b (Just $3)) }++KIND_PARAM :: { Expression A0 }+: INTEGER_LITERAL { $1 }+| VARIABLE { $1 }++STRING :: { Expression A0 }+: string { let TString s c = $1 in ExpValue () s $ ValString c }++cDATA :: { () } : {% pushContext ConData }+cIMPLICIT :: { () } : {% pushContext ConImplicit }+cNAMELIST :: { () } : {% pushContext ConNamelist }+cCOMMON :: { () } : {% pushContext ConCommon }+cPOP :: { () } : {% popContext }
+ src/Language/Fortran/Parser/Free/Lexer.x view
@@ -0,0 +1,1377 @@+-- -*- Mode: Haskell -*-+-- vim: ft=haskell+{+{-# LANGUAGE UndecidableInstances #-}++module Language.Fortran.Parser.Free.Lexer+ (+ -- * Main interface+ lexer, Token(..), vanillaAlexInput, AlexInput(..), LexAction++ -- * Internals+ , lexer'+ , StartCode(..)+ , StartCodeStatus(..)+ , scN+ ) where++import Prelude hiding (span)+import Data.Data+import Data.Maybe (fromMaybe)+import Data.List (foldl')+import Data.Char (toLower)+import Data.Word (Word8)+import qualified Data.ByteString.Char8 as B++import Control.Monad (join)+import Control.Monad.State (get)++import GHC.Generics++import Language.Fortran.Parser.Monad+import Language.Fortran.Version+import Language.Fortran.Util.Position+import Language.Fortran.Util.FirstParameter+import Language.Fortran.AST.RealLit (RealLit, parseRealLit)+import Language.Fortran.AST.Boz+import Language.Fortran.Parser.LexerUtils ( readIntOrBoz )++}++$digit = 0-9+$bit = 0-1+$octalDigit = 0-7+$hexDigit = [a-f $digit]++$letter = a-z+$alphanumeric = [$letter $digit \_]++$hash = [\#]++@label = $digit{1,5}+@name = $letter $alphanumeric*++@binary = b\'$bit+\'+@octal = o\'$octalDigit+\'+@hex = z\'$hexDigit+\'++@digitString = $digit++@kindParam = (@digitString|@name)+@bozLiteralConst = (@binary|@octal|@hex)++-- Real literals+$expLetter = [ed]+@exponent = [\-\+]? @digitString+@significand = @digitString? \. @digitString+@realLiteral = @significand ($expLetter @exponent)?+ | @digitString $expLetter @exponent+ -- The following complements @altRealLiteral . The reason it is+ -- included in the general case is to reduce the number of+ -- semantic predicates to be made while lexing.+ | @digitString \. $expLetter @exponent+@altRealLiteral = @digitString \.++@characterLiteralBeg = (@kindParam \_)? (\'|\")++--------------------------------------------------------------------------------+-- Start codes | Explanation+--------------------------------------------------------------------------------+-- 0 | For statement starters+-- scI | For statements that can come after logical IF+-- scC | To be used in lexCharacter, it only appears to force Happy to+-- | resolve it.+-- scT | For types+-- scN | For everything else+--------------------------------------------------------------------------------+tokens :-++<0> "/*" { skipCComment }+<0,scN> "!".*$ { adjustComment $ addSpanAndMatch TComment }++<0> $hash.*$ { lexHash }++<0,scN,scT> (\n\r|\r\n|\n) { resetPar >> toSC 0 >> addSpan TNewline }+<0,scN,scI,scT> [\t\ ]+ ;++<scN> "(" { leftPar }+<scN> ")" / { ifConditionEndP } { decPar >> toSC scI >> addSpan TRightPar }+<scN> ")" { decPar >> addSpan TRightPar }+<scN> "(/" / { notDefinedOperP } { addSpan TLeftInitPar }+<scN> "/)" / { notDefinedOperP } { addSpan TRightInitPar }+<scN> "[" / { notDefinedOperP } { addSpan TLeftInitPar }+<scN> "]" / { notDefinedOperP } { addSpan TRightInitPar }+<scN> "," { comma }+<scN> ";" { resetPar >> toSC 0 >> addSpan TSemiColon }+<scN> ":" { addSpan TColon }+<scN> "::" { addSpan TDoubleColon }+<scN> "=" { addSpan TOpAssign}+<scN> "=>" { addSpan TArrow }+<scN> "%" { addSpan TPercent }++<0,scI> @name / { partOfExpOrPointerAssignmentP } { addSpanAndMatch TId }+<0> @name / { constructNameP } { addSpanAndMatch TId }++-- Program units+<0> "program" { addSpan TProgram }+<0> "end"\ *"program" { addSpan TEndProgram }+<0> "function" { addSpan TFunction }+<scN> "function" / { typeSpecP } { addSpan TFunction }+<0> "end"\ *"function" { addSpan TEndFunction }+<scN> "result" / { resultP } { addSpan TResult }+<0> "pure" { toSC 0 >> addSpan TPure }+<0> "elemental" { toSC 0 >> addSpan TElemental }+<0> "recursive" { toSC 0 >> addSpan TRecursive }+<scN> "pure" / { typeSpecP } { toSC 0 >> addSpan TPure }+<scN> "elemental" / { typeSpecP } { toSC 0 >> addSpan TElemental }+<scN> "recursive" / { typeSpecP } { toSC 0 >> addSpan TRecursive }+<0> "subroutine" { addSpan TSubroutine }+<0> "end"\ *"subroutine" { addSpan TEndSubroutine }+<0> "block"\ *"data" { addSpan TBlockData }+<0> "end"\ *"block"\ *"data" { addSpan TEndBlockData }+<0> "module" { addSpan TModule }+<0> "end"\ *"module" { addSpan TEndModule }+<0> "contains" { addSpan TContains }+<0> "use" { addSpan TUse }+<scN> "only" / { useStP } { addSpan TOnly }+<0> "import" { addSpan TImport }+<0> "abstract" { addSpan TAbstract }+<0> "interface" { addSpan TInterface }+<scN> "interface" / { genericSpecP } { addSpan TInterface }+<0> "end"\ *"interface" { addSpan TEndInterface }+<0> "procedure" { addSpan TProcedure }+<0> "module"\ \ *"procedure" { addSpan TModuleProcedure }+<scN> "assignment"\ *"("\ *"="\ *")" / { genericSpecP } { addSpan TAssignment }+<scN> "operator" / { genericSpecP } { addSpan TOperator }+<0,scI> "call" { addSpan TCall }+<0,scI> "return" { addSpan TReturn }+<0> "entry" { addSpan TEntry }+<0> "include" { addSpan TInclude }++-- Type def related+<0,scT> "type" { addSpan TType }+<scN> "type" / { allocateP } { addSpan TType }+<0> "end"\ *"type" { addSpan TEndType }+<scN> "class" / { followsProcedureP } { addSpan TClass }+<0> "sequence" { addSpan TSequence }+<0> "enum" { addSpan TEnum }+<0> "end"\ *"enum" { addSpan TEndEnum }+<0> "enumerator" { addSpan TEnumerator }++-- Intrinsic types+<0,scT> "integer" { addSpan TInteger }+<scN> "integer" / { allocateP } { addSpan TInteger }+<0,scT> "real" { addSpan TReal }+<scN> "real" / { allocateP } { addSpan TReal }+<0,scT> "double"\ *"precision" { addSpan TDoublePrecision }+<scN> "double"\ *"precision" / { allocateP } { addSpan TDoublePrecision }+<0,scT> "logical" { addSpan TLogical }+<scN> "logical" / { allocateP } { addSpan TLogical }+<0,scT> "character" { addSpan TCharacter }+<scN> "character" / { allocateP } { addSpan TCharacter }+<0,scT> "complex" { addSpan TComplex }+<scN> "complex" / { allocateP } { addSpan TComplex }++<scN> "kind" / { selectorP } { addSpan TKind }+<scN> "len" / { selectorP } { addSpan TLen }++-- Attributes+<0> "public" { addSpan TPublic }+<scN> "public" / { attributeP } { addSpan TPublic }+<0> "private" { addSpan TPrivate }+<scN> "private" / { attributeP } { addSpan TPrivate }+<0> "protected" { addSpan TProtected }+<scN> "protected" / { attributeP } { addSpan TProtected }+<0> "parameter" { addSpan TParameter }+<scN> "parameter" / { attributeP } { addSpan TParameter }+<0> "allocatable" { addSpan TAllocatable }+<scN> "allocatable" / { attributeP } { addSpan TAllocatable }+<0> "asynchronous" { addSpan TAsynchronous }+<scN> "asynchronous" / { attributeP } { addSpan TAsynchronous }+<0> "dimension" { addSpan TDimension }+<scN> "dimension" / { attributeP } { addSpan TDimension }+<0> "external" { addSpan TExternal }+<scN> "external" / { attributeP } { addSpan TExternal }+<0> "intent" { addSpan TIntent }+<scN> "intent" / { attributeP } { addSpan TIntent }+<0> "intrinsic" { addSpan TIntrinsic }+<scN> "intrinsic" / { attributeP } { addSpan TIntrinsic }+<0> "non_intrinsic" { addSpan TNonIntrinsic }+<scN> "non_intrinsic" / { attributeP } { addSpan TNonIntrinsic }+<0> "optional" { addSpan TOptional }+<scN> "optional" / { attributeP } { addSpan TOptional }+<0> "pointer" { addSpan TPointer }+<scN> "pointer" / { attributeP } { addSpan TPointer }+<0> "save" { addSpan TSave }+<scN> "save" / { attributeP } { addSpan TSave }+<0> "target" { addSpan TTarget }+<scN> "target" / { attributeP } { addSpan TTarget }+<0> "save" { addSpan TSave }+<scN> "save" / { attributeP } { addSpan TSave }+<0> "value" { addSpan TValue }+<scN> "value" / { attributeP } { addSpan TValue }+<0> "volatile" { addSpan TVolatile }+<scN> "volatile" / { attributeP } { addSpan TVolatile }++-- Attribute values+<scN> "in"\ *"out" / { followsIntentP } { addSpan TInOut }+<scN> "in" / { followsIntentP } { addSpan TIn }+<scN> "out" / { followsIntentP } { addSpan TOut }++-- language-binding-spec+<scN> "bind" / { bindP } { addSpan TBind }+<scN> "name" / { followsCP } { addSpan TName }+<scN> "c" / { followsBindP } { addSpan TC }++-- Control flow+<0> "do" { addSpan TDo }+<scN> "do" / { followsColonP } { addSpan TDo }+<0> "end"\ *"do" { addSpan TEndDo }+<scN> "while" / { followsDoWithOptLabelP } { addSpan TWhile }+<0> "if" { addSpan TIf }+<scN> "if" / { followsColonP } { addSpan TIf }+<scI> "then" { addSpan TThen }+<0> "else" { addSpan TElse }+<0> "else"\ *"if" { addSpan TElsif }+<0> "end"\ *"if" { addSpan TEndIf }+<0> "select"\ *"case" { addSpan TSelectCase }+<scN> "select"\ *"case" / { followsColonP } { addSpan TSelectCase }+<0> "case" { addSpan TCase }+<0> "end"\ *"select" { addSpan TEndSelect }+<scN> "default" / { caseStP } { addSpan TDefault }+<0,scI> "cycle" { addSpan TCycle }+<0,scI> "exit" { addSpan TExit }+<0,scI> "go"\ *"to" { addSpan TGoto }+<0,scI> "assign" { addSpan TAssign }+<scN> "to" / { assignStP } { addSpan TTo }+<0,scI> "continue" { addSpan TContinue }+<0,scI> "stop" { addSpan TStop }+<0,scI> "pause" { addSpan TPause }+<0> "forall" { addSpan TForall }+<0> "end"\ *"forall" { addSpan TEndForall }+<0> "associate" { addSpan TAssociate }+<scN> "associate" / { followsColonP } { addSpan TAssociate }+<0> "end"\ *"associate" { addSpan TEndAssociate }+++-- Where construct+<0,scI> "where" { addSpan TWhere }+<scN> "where" / { labelledWhereP } { addSpan TWhere }+<0> "elsewhere" { addSpan TElsewhere }+<0> "else"\ *"where" { addSpan TElsewhere }+<0> "end"\ *"where" { addSpan TEndWhere }++-- Beginning keyword+<0> "data" { addSpan TData }+<0,scI> "allocate" { addSpan TAllocate }+<scN> "stat" / { allocateP } { addSpan TStat }+<scN> "errmsg" / { allocateP } { addSpan TErrMsg }+<scN> "source" / { allocateP } { addSpan TSource }+<0,scI> "deallocate" { addSpan TDeallocate }+<0,scI> "nullify" { addSpan TNullify }+<0> "namelist" { addSpan TNamelist }+<0> "implicit" { toSC scT >> addSpan TImplicit }+<0> "equivalence" { addSpan TEquivalence }+<0> "common" { addSpan TCommon }+<0> "end" { addSpan TEnd }++<scT> "none" { addSpan TNone }++-- I/O+<0,scI> "open" { addSpan TOpen }+<0,scI> "close" { addSpan TClose }+<0,scI> "read" { addSpan TRead }+<0,scI> "write" { addSpan TWrite }+<0,scI> "print" { addSpan TPrint }+<0,scI> "backspace" { addSpan TBackspace }+<0,scI> "rewind" { addSpan TRewind }+<0,scI> "inquire" { addSpan TInquire }+<0,scI> "end"\ *"file" { addSpan TEndfile }+<0> "flush" { addSpan TFlush }+<scN> "unit" / { followsFlushP } { addSpan TUnit }+<scN> "iostat" / { followsFlushP } { addSpan TIOStat }+<scN> "iomsg" / { followsFlushP } { addSpan TIOMsg }+<scN> "err" / { followsFlushP } { addSpan TErr }++-- Format+<0> "format" { addSpan TFormat }+<scN> "(".*")" / { formatP } { addSpanAndMatch TBlob }++-- Literals+<scN> "_" { addSpan TUnderscore }+<0> @label { toSC 0 >> addSpanAndMatch TIntegerLiteral }+<scN,scI> @digitString { addSpanAndMatch TIntegerLiteral }+<scN> @bozLiteralConst { addSpanAndMatch $ \ss s -> TBozLiteral ss (parseBoz s) }++<scN> @realLiteral { addSpanAndMatch $ \ss s -> TRealLiteral ss (parseRealLit s) }+<scN> @altRealLiteral / { notPrecedingDotP } { addSpanAndMatch $ \ss s -> TRealLiteral ss (parseRealLit s) }++<scN,scC> @characterLiteralBeg { lexCharacter }++<scN> ".true." { addSpan (\s -> TLogicalLiteral s True) }+<scN> ".false." { addSpan (\s -> TLogicalLiteral s False) }++-- Operators+<scN> ("."$letter+"."|"**"|\*|\/|\+|\-) / { opP } { addSpanAndMatch TOpCustom }+<scN> "**" { addSpan TOpExp }+<scN> "+" { addSpan TOpPlus }+<scN> "-" { addSpan TOpMinus }+<scN> "*" { addSpan TStar }+<scN> "/" { slashOrDivision }+<scN> ".or." { addSpan TOpOr }+<scN> ".and." { addSpan TOpAnd }+<scN> ".not." { addSpan TOpNot }+<scN> ".eqv." { addSpan TOpEquivalent }+<scN> ".neqv." { addSpan TOpNotEquivalent }+<scN> (".eq."|"==") { addSpan TOpEQ }+<scN> (".ne."|"/=") { addSpan TOpNE }+<scN> (".lt."|"<") { addSpan TOpLT }+<scN> (".le."|"<=") { addSpan TOpLE }+<scN> (".gt."|">") { addSpan TOpGT }+<scN> (".ge."|">=") { addSpan TOpGE }+<scN> "." $letter+ "." { addSpanAndMatch TOpCustom }++<scN> @name { addSpanAndMatch TId }++{++--------------------------------------------------------------------------------+-- Predicated lexer helpers+--------------------------------------------------------------------------------++formatP :: User -> AlexInput -> Int -> AlexInput -> Bool+formatP _ _ _ ai+ | Just TFormat{} <- aiPreviousToken ai = True+ | otherwise = False++followsDoWithOptLabelP :: User -> AlexInput -> Int -> AlexInput -> Bool+followsDoWithOptLabelP _ _ _ ai+ -- DO ...+ | Just TDo {} <- aiPreviousToken ai = True++ -- DO 10 ...+ | TDo{}:TIntegerLiteral{}:[] <- prevTokens = True++ | otherwise = False+ where+ prevTokens = reverse . aiPreviousTokensInLine $ ai++followsColonP :: User -> AlexInput -> Int -> AlexInput -> Bool+followsColonP _ _ _ ai+ | Just TColon{} <- aiPreviousToken ai = True+ | otherwise = False++labelledWhereP :: User -> AlexInput -> Int -> AlexInput -> Bool+labelledWhereP _ _ _ ai+ | TId{}:TColon{}:[] <- prevTokens = True+ | otherwise = False+ where+ prevTokens = reverse . aiPreviousTokensInLine $ ai++selectorP :: User -> AlexInput -> Int -> AlexInput -> Bool+selectorP user _ _ ai =+ followsType && nextTokenIsOpAssign && precedesDoubleColon ai+ where+ nextTokenIsOpAssign = nextTokenConstr user ai == (Just . fillConstr $ TOpAssign)+ followsType =+ case searchBeforePar (aiPreviousTokensInLine ai) of+ Just x -> isTypeSpec x+ Nothing -> False+ searchBeforePar [] = Nothing+ searchBeforePar (x:xs)+ | TLeftPar{} <- x = if null xs then Nothing else (Just $ head xs)+ | otherwise = searchBeforePar xs++ifConditionEndP :: User -> AlexInput -> Int -> AlexInput -> Bool+ifConditionEndP (User _ pc) _ _ ai+ | (TIf{}:_) <- prevTokens = pc == ParanthesesCount 1 False+ | (TIntegerLiteral{}:TIf{}:_) <- prevTokens = pc == ParanthesesCount 1 False+ | (TId{}:TColon{}:TIf{}:_) <- prevTokens = pc == ParanthesesCount 1 False+ | (TElsif{}:_) <- prevTokens = pc == ParanthesesCount 1 False+ | otherwise = False+ where+ prevTokens = reverse . aiPreviousTokensInLine $ ai++opP :: User -> AlexInput -> Int ->AlexInput -> Bool+opP _ _ _ ai+ | (TLeftPar{}:TOperator{}:_) <- aiPreviousTokensInLine ai = True+ | otherwise = False++partOfExpOrPointerAssignmentP :: User -> AlexInput -> Int -> AlexInput -> Bool+partOfExpOrPointerAssignmentP (User fv pc) _ _ ai =+ case unParse (lexer $ f False (0::Integer)) ps of+ ParseOk True _ -> True+ _ -> False+ where+ ps = ParseState+ { psAlexInput = ai { aiStartCode = StartCode scN Return }+ , psVersion = fv+ , psFilename = "<unknown>"+ , psParanthesesCount = pc+ , psContext = [ ConStart ] }+ f leftParSeen parCount token+ | not leftParSeen =+ case token of+ TNewline{} -> return False+ TSemiColon{} -> return False+ TEOF{} -> return False+ TPercent{} -> return True+ TArrow{} -> return True+ TOpAssign{} -> return True+ TLeftPar{} -> lexer $ f True 1+ TLeftPar2{} -> lexer $ f True 1+ _ -> return False+ | parCount == 0 =+ case token of+ TOpAssign{} -> return True+ TArrow{} -> return True+ TPercent{} -> return True+ TLeftPar{} -> lexer $ f True 1+ TLeftPar2{} -> lexer $ f True 1+ _ -> return False+ | parCount > 0 =+ case token of+ TNewline{} -> return False+ TSemiColon{} -> return False+ TEOF{} -> return False+ TLeftPar{} -> lexer $ f True (parCount + 1)+ TLeftPar2{} -> lexer $ f True (parCount + 1)+ TRightPar{} -> lexer $ f True (parCount - 1)+ _ -> lexer $ f True parCount+ | otherwise =+ error "Error while executing part of expression assignment predicate."++precedesDoubleColon :: AlexInput -> Bool+precedesDoubleColon ai = not . flip seenConstr ai . fillConstr $ TDoubleColon++parenLevel :: [Token] -> Int+parenLevel = foldl' f 0+ where+ f n tok | fillConstr TLeftPar == toConstr tok = n + 1+ | fillConstr TRightPar == toConstr tok = n - 1+ | otherwise = n++allocateP :: User -> AlexInput -> Int -> AlexInput -> Bool+allocateP _ _ _ ai+ | alloc:lpar:rest <- prevTokens+ , toConstr alloc `elem` [fillConstr TAllocate, fillConstr TDeallocate]+ , fillConstr TLeftPar == toConstr lpar+ = null rest || (followsComma && parenLevel prevTokens == 1)+ | otherwise = False+ where+ prevTokens = reverse . aiPreviousTokensInLine $ ai+ followsComma+ | Just TComma{} <- aiPreviousToken ai = True+ | otherwise = False++attributeP :: User -> AlexInput -> Int -> AlexInput -> Bool+attributeP _ _ _ ai = followsComma && precedesDoubleColon ai && lineStartOK+ where+ followsComma+ | Just TComma{} <- aiPreviousToken ai = True+ | otherwise = False++ lineStartOK+ -- matches e.g.: TYPE (FOO), ATTR+ | typ:lpar:_:rpar:com:_ <- prevTokens+ , toConstr typ `elem` [fillConstr TType, fillConstr TClass]+ , toConstr lpar == fillConstr TLeftPar+ , toConstr rpar == fillConstr TRightPar+ = fillConstr TComma == toConstr com++ -- matches e.g.: TYPE FOO, ATTR+ | typ:com:_ <- prevTokens+ , toConstr typ == fillConstr TType+ = fillConstr TComma == toConstr com++ -- matches e.g.: INTEGER (KIND=...), ATTR+ -- or: PROCEDURE (...), ATTR+ | tok:lpar:rest <- prevTokens+ , isTypeSpec tok || fillConstr TProcedure == toConstr tok+ , fillConstr TLeftPar == toConstr lpar+ , (_, _:com:_) <- break ((fillConstr TRightPar ==) . toConstr) rest+ = fillConstr TComma == toConstr com++ -- matches e.g.: INTEGER*NUM, ATTR+ | tok:star:num:com:_ <- prevTokens+ , isTypeSpec tok+ , fillConstr TStar == toConstr star+ , TIntegerLiteral{} <- num+ = fillConstr TComma == toConstr com++ -- matches e.g.: INTEGER, ATTR+ -- or: USE, ATTR+ | tok:com:_ <- prevTokens+ , isTypeSpec tok || fillConstr TUse == toConstr tok+ = fillConstr TComma == toConstr com++ | otherwise = False++ prevTokens = reverse . aiPreviousTokensInLine $ ai++bindP :: User -> AlexInput -> Int -> AlexInput -> Bool+bindP _ _ _ ai = (followsRightPar && isFunSub) || (followsComma && isProcEnum)+ where+ followsComma+ | Just TComma{} <- aiPreviousToken ai = True+ | otherwise = False+ followsRightPar+ | Just TRightPar{} <- aiPreviousToken ai = True+ | otherwise = False+ isFunSub = flip any prevTokens $ \ token ->+ fillConstr TFunction == toConstr token ||+ fillConstr TSubroutine == toConstr token+ isProcEnum = flip any prevTokens $ \ token ->+ fillConstr TProcedure == toConstr token ||+ fillConstr TEnum == toConstr token+ prevTokens = reverse . aiPreviousTokensInLine $ ai++constructNameP :: User -> AlexInput -> Int -> AlexInput -> Bool+constructNameP user _ _ ai =+ case nextTokenConstr user ai of+ Just constr -> constr == fillConstr TColon+ _ -> False++genericSpecP :: User -> AlexInput -> Int -> AlexInput -> Bool+genericSpecP _ _ _ ai = Just True == do+ constr <- prevTokenConstr ai+ if constr `elem` fmap fillConstr [ TAbstract, TInterface, TPublic, TPrivate, TProtected ]+ then return True+ else if constr `elem` fmap fillConstr [ TComma, TDoubleColon, TColon ]+ then return $ seenConstr (fillConstr TPublic) ai ||+ seenConstr (fillConstr TPrivate) ai ||+ seenConstr (fillConstr TProtected) ai ||+ seenConstr (fillConstr TOnly) ai+ else Nothing++notDefinedOperP :: User -> AlexInput -> Int -> AlexInput -> Bool+notDefinedOperP _ _ _ ai+ | prevToken:_ <- prevTokens+ , fillConstr TOperator == toConstr prevToken = False+ | prevToken:prevToken':_ <- prevTokens+ , fillConstr TLeftPar == toConstr prevToken+ , fillConstr TOperator == toConstr prevToken' = False+ | otherwise = True+ where+ prevTokens = aiPreviousTokensInLine ai++typeSpecP :: User -> AlexInput -> Int -> AlexInput -> Bool+typeSpecP _ _ _ ai+ | (prevToken:_) <- prevTokens+ , isTypeSpec prevToken = True+ | otherwise = isTypeSpecImmediatelyBefore $ reverse prevTokens+ where+ isTypeSpecImmediatelyBefore tokens@(_:xs)+ | isTypeSpec tokens = True+ | otherwise = isTypeSpecImmediatelyBefore xs+ isTypeSpecImmediatelyBefore [] = False+ prevTokens = aiPreviousTokensInLine ai++resultP :: User -> AlexInput -> Int -> AlexInput -> Bool+resultP _ _ _ ai =+ (flip seenConstr ai . fillConstr $ TFunction) &&+ prevTokenConstr ai == (Just $ fillConstr TRightPar)++notPrecedingDotP :: User -> AlexInput -> Int -> AlexInput -> Bool+notPrecedingDotP user _ _ ai = not $+ nextTokenConstr user ai == (Just $ toConstr (TId undefined undefined))++followsIntentP :: User -> AlexInput -> Int -> AlexInput -> Bool+followsIntentP _ _ _ ai =+ (map toConstr . take 2 . aiPreviousTokensInLine) ai ==+ map fillConstr [ TLeftPar, TIntent ]++followsProcedureP :: User -> AlexInput -> Int -> AlexInput -> Bool+followsProcedureP _ _ _ ai =+ (map toConstr . take 2 . aiPreviousTokensInLine) ai ==+ map fillConstr [ TLeftPar, TProcedure ]++followsBindP :: User -> AlexInput -> Int -> AlexInput -> Bool+followsBindP _ _ _ ai =+ (map toConstr . take 2 . aiPreviousTokensInLine) ai ==+ map fillConstr [ TLeftPar, TBind ]++followsCP :: User -> AlexInput -> Int -> AlexInput -> Bool+followsCP _ _ _ ai =+ (map toConstr . take 2 . aiPreviousTokensInLine) ai ==+ map fillConstr [ TComma, TC ]++followsFlushP :: User -> AlexInput -> Int -> AlexInput -> Bool+followsFlushP _ _ _ ai = not (null toks) && fillConstr TFlush == toConstr (last toks)+ where toks = aiPreviousTokensInLine ai++useStP :: User -> AlexInput -> Int -> AlexInput -> Bool+useStP _ _ _ ai = seenConstr (toConstr $ TUse undefined) ai++caseStP :: User -> AlexInput -> Int -> AlexInput -> Bool+caseStP _ _ _ ai = prevTokenConstr ai == (Just $ fillConstr TCase)++assignStP :: User -> AlexInput -> Int -> AlexInput -> Bool+assignStP _ _ _ ai = seenConstr (fillConstr TAssign) ai++prevTokenConstr :: AlexInput -> Maybe Constr+prevTokenConstr ai = toConstr <$> aiPreviousToken ai++nextTokenConstr :: User -> AlexInput -> Maybe Constr+nextTokenConstr (User fv pc) ai =+ case unParse lexer' parseState of+ ParseOk token _ -> Just $ toConstr token+ _ -> Nothing+ where+ parseState = ParseState+ { psAlexInput = ai+ , psParanthesesCount = pc+ , psVersion = fv+ , psFilename = "<unknown>"+ , psContext = [ ConStart ] }++seenConstr :: Constr -> AlexInput -> Bool+seenConstr candidateConstr ai =+ candidateConstr `elem` (toConstr <$> aiPreviousTokensInLine ai)++fillConstr = toConstr . ($ undefined)++--------------------------------------------------------------------------------+-- Lexer helpers+--------------------------------------------------------------------------------++adjustComment :: LexAction (Maybe Token) -> LexAction (Maybe Token)+adjustComment action = do+ mTok <- action+ case mTok of+ Just (TComment s (_:xs)) -> return $ Just $ TComment s xs+ _ -> error "Either not a comment token or matched empty."++leftPar :: LexAction (Maybe Token)+leftPar = do+ incPar+ context <- topContext+ if context == ConImplicit+ then do+ parseState <- get+ case unParse f parseState of+ ParseOk tokenCons _ -> do+ span <- getLexemeSpan+ return $ Just $ tokenCons span+ ParseFailed _ -> fail "Left parantheses is not matched."+ else addSpan TLeftPar+ where+ f :: LexAction (SrcSpan -> Token)+ f = do+ (ParanthesesCount pc _) <- getParanthesesCount+ mPrevToken <- aiPreviousToken <$> getAlex+ case mPrevToken of+ Just TRightPar{} | pc == 0 -> do+ _ <- getLexemeSpan+ curToken <- lexer'+ case curToken of+ TComma{} -> return TLeftPar2+ TNewline{} -> return TLeftPar2+ TSemiColon{} -> return TLeftPar2+ TEOF{} -> return TLeftPar2+ _ -> return TLeftPar+ _ -> lexer' >> f++comma :: LexAction (Maybe Token)+comma = do+ context <- topContext+ case context of+ ConImplicit -> do+ mToken <- aiPreviousToken <$> getAlex+ case mToken of+ Just TRightPar{} -> toSC scT >> addSpan TComma+ _ -> addSpan TComma+ ConNamelist -> secondCommaIfSlashFollows+ ConCommon -> secondCommaIfSlashFollows+ _ -> addSpan TComma+ where+ secondCommaIfSlashFollows = do+ parseState <- get+ case unParse lexer' parseState of+ ParseOk TOpDivision{} _ -> addSpan TComma2+ ParseFailed _ -> fail "Expecting variable name or slash."+ _ -> addSpan TComma++slashOrDivision :: LexAction (Maybe Token)+slashOrDivision = do+ context <- topContext+ case context of+ ConData -> addSpan TSlash+ _ -> addSpan TOpDivision++addSpan :: (SrcSpan -> Token) -> LexAction (Maybe Token)+addSpan cons = do+ s <- getLexemeSpan+ return $ Just $ cons s++addSpanAndMatch :: (SrcSpan -> String -> Token) -> LexAction (Maybe Token)+addSpanAndMatch cons = do+ s <- getLexemeSpan+ m <- getMatch+ return $ Just $ cons s m++getLexeme :: LexAction Lexeme+getLexeme = do+ ai <- getAlex+ return $ aiLexeme ai++putLexeme :: Lexeme -> LexAction ()+putLexeme lexeme = do+ ai <- getAlex+ putAlex $ ai { aiLexeme = lexeme }++resetLexeme :: LexAction ()+resetLexeme = putLexeme initLexeme++getMatch :: LexAction String+getMatch = do+ lexeme <- getLexeme+ return $ (reverse . lexemeMatch) lexeme++putMatch :: String -> LexAction ()+putMatch newMatch = do+ lexeme <- getLexeme+ putLexeme $ lexeme { lexemeMatch = reverse newMatch }++instance Spanned Lexeme where+ getSpan lexeme = SrcSpan (lexemeStart lexeme) (lexemeEnd lexeme)+ setSpan _ = error "Lexeme span cannot be set."++updatePreviousToken :: Maybe Token -> LexAction ()+updatePreviousToken maybeToken = do+ ai <- getAlex+ putAlex $ ai { aiPreviousToken = maybeToken }++addToPreviousTokensInLine :: Token -> LexAction ()+addToPreviousTokensInLine token = do+ ai <- getAlex+ putAlex $+ case token of+ TNewline _ -> updatePrevTokens ai [ ]+ TSemiColon _ -> updatePrevTokens ai [ ]+ t -> updatePrevTokens ai $ t : aiPreviousTokensInLine ai+ where+ updatePrevTokens ai tokens = ai { aiPreviousTokensInLine = tokens }++checkPreviousTokensInLine :: (Token -> Bool) -> AlexInput -> Bool+checkPreviousTokensInLine prop ai = any prop $ aiPreviousTokensInLine ai++getLexemeSpan :: LexAction SrcSpan+getLexemeSpan = do+ lexeme <- getLexeme+ return $ getSpan lexeme++-- Automata for character literal parsing is given below. Wherever it says '+-- you can replace ", whichever is used depends on what the first matched+-- character is and they are dual in their nature.+--+-- else+-- +-++-- | v+-- +-+ Nothing +-++-- +---> |0|---------->|3|+-- +-> +-+ +-++-- | |+-- ' | | '+-- | v+-- | +-+ Nothing +-++-- +---|1|---------->|2|+-- +-+ +-++-- | ^+-- +-------------++-- else+--+-- For more information please refer to Fortran 90 standard's section related+-- to character constants.+lexCharacter :: LexAction (Maybe Token)+lexCharacter = do+ alex <- getAlex+ putAlex $ alex { aiStartCode = StartCode scC Stable }+ match <- getMatch+ let boundaryMarker = last match+ _lexChar (0::Integer) boundaryMarker+ where+ _lexChar 0 bm = do+ alex <- getAlex+ case alexGetByte alex of+ Just (_, newAlex) -> do+ putAlex newAlex+ m <- getMatch+ if last m == bm+ then _lexChar 1 bm+ else _lexChar 0 bm+ Nothing -> fail "Unmatched character literal."+ _lexChar 1 bm = do+ alex <- getAlex+ case alexGetByte alex of+ Just (_, newAlex) -> do+ let m = lexemeMatch . aiLexeme $ newAlex+ if head m == bm+ then do+ putAlex newAlex+ putMatch . reverse . tail $ m+ _lexChar 0 bm+ else _lexChar 2 bm+ Nothing -> _lexChar 2 bm+ _lexChar 2 _ = do+ alex <- getAlex+ putAlex $ alex { aiStartCode = StartCode scN Return }+ match <- getMatch+ putMatch . init . tail $ match+ addSpanAndMatch TString+ _lexChar _ _ = do fail "unhandled lexCharacter"++toSC :: Int -> LexAction ()+toSC startCode = do+ alex <- getAlex+ putAlex $ alex { aiStartCode = StartCode startCode Return }++stabiliseStartCode :: LexAction ()+stabiliseStartCode = do+ alex <- getAlex+ let sc = aiStartCode alex+ putAlex $ alex { aiStartCode = sc { scStatus = Stable } }++normaliseStartCode :: LexAction ()+normaliseStartCode = do+ alex <- getAlex+ let startCode = aiStartCode alex+ case scStatus startCode of+ Return -> putAlex $ alex { aiStartCode = StartCode scN Stable }+ Stable -> return ()++--------------------------------------------------------------------------------+-- AlexInput & related definitions+--------------------------------------------------------------------------------++invalidPosition :: Position+invalidPosition = Position 0 0 0 "" Nothing++{-# INLINE isValidPosition #-}+isValidPosition :: Position -> Bool+isValidPosition pos = posLine pos > 0++data Lexeme = Lexeme+ { lexemeMatch :: !String+ , lexemeStart :: {-# UNPACK #-} !Position+ , lexemeEnd :: {-# UNPACK #-} !Position+ , lexemeIsCmt :: !Bool+ } deriving (Show)++initLexeme :: Lexeme+initLexeme = Lexeme+ { lexemeMatch = ""+ , lexemeStart = invalidPosition+ , lexemeEnd = invalidPosition+ , lexemeIsCmt = False }++data StartCodeStatus = Return | Stable deriving (Show)++data StartCode = StartCode+ { scActual :: {-# UNPACK #-} !Int+ , scStatus :: !StartCodeStatus }+ deriving (Show)++data AlexInput = AlexInput+ { aiSourceBytes :: !B.ByteString+ , aiPosition :: {-# UNPACK #-} !Position+ , aiEndOffset :: {-# UNPACK #-} !Int+ , aiPreviousChar :: {-# UNPACK #-} !Char+ , aiLexeme :: {-# UNPACK #-} !Lexeme+ , aiStartCode :: {-# UNPACK #-} !StartCode+ , aiPreviousToken :: !(Maybe Token)+ , aiPreviousTokensInLine :: !([ Token ])+ } deriving (Show)++instance Loc AlexInput where+ getPos = aiPosition++instance LastToken AlexInput Token where+ getLastToken = aiPreviousToken++type LexAction a = Parse AlexInput Token a++vanillaAlexInput :: String -> B.ByteString -> AlexInput+vanillaAlexInput fn bs = AlexInput+ { aiSourceBytes = bs+ , aiPosition = initPosition { filePath = fn }+ , aiEndOffset = B.length bs+ , aiPreviousChar = '\n'+ , aiLexeme = initLexeme+ , aiStartCode = StartCode 0 Return+ , aiPreviousToken = Nothing+ , aiPreviousTokensInLine = [ ] }++updateLexeme :: Char -> Position -> AlexInput -> AlexInput+updateLexeme !char !p !ai = ai { aiLexeme = Lexeme (char:match) start' p isCmt' }+ where+ Lexeme match start _ isCmt = aiLexeme ai+ start' = if isValidPosition start then start else p+ isCmt' = isCmt || (null match && char == '!')++-- Fortran version and parantheses count to be used by alexScanUser+data User = User FortranVersion ParanthesesCount++--------------------------------------------------------------------------------+-- Definitions needed for alexScanUser+--------------------------------------------------------------------------------++data Move = Continuation | Char | Newline++alexGetByte :: AlexInput -> Maybe (Word8, AlexInput)+alexGetByte !ai+ -- When all characters are already read+ | posAbsoluteOffset _position == aiEndOffset ai = Nothing+ -- Skip the continuation line altogether+ | isContinuation ai = alexGetByte . skipContinuation $ ai+ -- Read genuine character and advance. Also covers white sensitivity.+ | otherwise =+ Just ( fromIntegral . fromEnum $ _curChar+ , updateLexeme _curChar _position+ ai+ { aiPosition =+ case _curChar of+ '\n' -> advance Newline _position+ _ -> advance Char _position+ , aiPreviousChar = _curChar })+ where+ _curChar = currentChar ai+ _position = aiPosition ai++alexInputPrevChar :: AlexInput -> Char+alexInputPrevChar ai = aiPreviousChar ai++currentChar :: AlexInput -> Char+currentChar !ai+ -- case sensitivity matters only in character literals+ | sCode == scC = _currentChar+ | 'A' <= _currentChar &&+ _currentChar <= 'Z' = {-# SCC toLower_currentChar #-} toLower _currentChar+ | otherwise = _currentChar+ where+ sCode = scActual (aiStartCode ai)+ -- _currentChar = w2c (BU.unsafeIndex srcBytes i)+ _currentChar = B.index srcBytes absOff+ srcBytes = aiSourceBytes ai+ absOff = posAbsoluteOffset pos+ pos = aiPosition ai++advanceWithoutContinuation :: AlexInput -> Maybe AlexInput+advanceWithoutContinuation !ai+ -- When all characters are already read+ | posAbsoluteOffset _position == aiEndOffset ai =+ Nothing+ -- Read genuine character and advance. Also covers white sensitivity.+ | otherwise =+ Just $! ai { aiPosition =+ case _curChar of+ '\n' -> advance Newline _position+ _ -> advance Char _position+ , aiPreviousChar = _curChar }+ where+ _curChar = currentChar ai+ _position = aiPosition ai++isContinuation :: AlexInput -> Bool+isContinuation !ai =+ -- No continuation while lexing a character literal.+ (scActual . aiStartCode) ai /= scC+ -- No continuation while lexing a comment.+ && (null match || not (lexemeIsCmt lexeme))+ && _isContinuation ai (0::Integer)+ where+ match = lexemeMatch lexeme+ lexeme = aiLexeme $ ai+ _isContinuation !ai' 0 =+ if currentChar ai' == '&'+ then _advance ai'+ else False+ _isContinuation !ai' 1 =+ case currentChar ai' of+ ' ' -> _advance ai'+ '\t' -> _advance ai'+ '\r' -> _advance ai'+ '!' -> True+ '\n' -> True+ _ -> False+ _isContinuation _ _ = False+ _advance :: AlexInput -> Bool+ _advance !ai' =+ case advanceWithoutContinuation ai' of+ Just ai'' -> _isContinuation ai'' (1::Integer)+ Nothing -> False++-- Here's the skip continuation automaton:+--+-- white white,\n+-- +-+ +-++-- | v | v +---++-- +-+ & +-+ \n +-+ & |---|+-- +-->|0|------>|1|------->|3|------->||4||+-- +-+ +-+ +-+----+ |---|+-- | ^ | +---++-- |! | |+-- v | |else+-- +->+-+ | v+-- else| |2|---------+ +---++-- +--+-+ |---|+-- ||5||+-- |---|+-- +---++--+-- For more information refer to Fortran 90 standard.+-- This version is more permissive than the specification+-- as it allows empty lines to be used between continuations.+skipContinuation :: AlexInput -> AlexInput+skipContinuation ai' = _skipCont ai' (0::Integer)+ where+ _skipCont ai 0 =+ if currentChar ai == '&'+ then _advance ai 1+ else error "This case is excluded by isContinuation."+ _skipCont ai 1 =+ let _curChar = currentChar ai in+ if _curChar `elem` [' ', '\t', '\r']+ then _advance ai 1+ else if _curChar == '!'+ then _advance ai 2+ else if _curChar == '\n'+ then _advance ai 3+ else+ error $+ join [ "Did not expect non-blank/non-comment character after "+ , "continuation symbol (&)." ]+ _skipCont ai 2 =+ if currentChar ai == '\n'+ then _advance ai 3+ else _advance ai 2+ _skipCont ai 3 =+ let _curChar = currentChar ai in+ if _curChar `elem` [' ', '\t', '\r', '\n']+ then _advance ai 3+ else if _curChar == '!'+ then _advance ai 2+ else if _curChar == '&'+ -- This state accepts as if there were no spaces between the broken+ -- line and whatever comes after second &. This is implicitly state (4)+ then fromMaybe (error "File has ended prematurely during a continuation.")+ (advanceWithoutContinuation ai)+ -- This state accepts but the broken line delimits the previous token.+ -- This is implicitly state (5). To achieve this, it returns the+ -- previous ai, which either has whitespace or newline, so it will+ -- nicely delimit.+ else ai+ _skipCont _ _ = error "unhandled _skipCont in skipContinuation"+ _advance ai state =+ case advanceWithoutContinuation ai of+ Just ai'' -> _skipCont ai'' state+ Nothing -> error "File has ended prematurely during a continuation."++-- skip a C comment (read until first "*/")+skipCComment :: LexAction (Maybe Token)+skipCComment = do+ let loop (Just ai) 0 | currentChar ai == '*' = loop (advanceWithoutContinuation ai) 1+ | otherwise = loop (advanceWithoutContinuation ai) 0+ loop (Just ai) 1 | currentChar ai == '/' = ai `fromMaybe` advanceWithoutContinuation ai+ | otherwise = loop (advanceWithoutContinuation ai) 0+ loop _ _ = error "File has ended prematurely during a C comment."+ ai <- getAlex+ putAlex $ loop (Just ai) (0 :: Int)+ return Nothing++advance :: Move -> Position -> Position+advance move position =+ case move of+ Newline ->+ position+ { posAbsoluteOffset = _absl + 1 , posColumn = 1 , posLine = _line + 1 }+ Char ->+ position { posAbsoluteOffset = _absl + 1 , posColumn = _col + 1 }+-- for now just return the original position+ _ -> position { posAbsoluteOffset = _absl, posColumn = _col }+ where+ _col = posColumn position+ _line = posLine position+ _absl = posAbsoluteOffset position++-- Handle pragmas that begin with #+lexHash :: LexAction (Maybe Token)+lexHash = do+ ai <- getAlex+ m <- getMatch+ case words (drop 1 m) of+ -- 'line' pragma - rewrite the current line and filename+ "line":lineStr:_+ | line <- readIntOrBoz lineStr -> do+ let revdropWNQ = reverse . drop 1 . dropWhile (flip notElem "'\"")+ let file = revdropWNQ . revdropWNQ $ m+ let lineOffs = fromIntegral line - posLine (aiPosition ai) - 1+ let newP = (aiPosition ai) { posPragmaOffset = Just (lineOffs, file)+ , posColumn = 1 }+ putAlex $ ai { aiPosition = newP }+ _ -> return ()+ return Nothing++--------------------------------------------------------------------------------+-- Lexer definition+--------------------------------------------------------------------------------++lexer :: (Token -> LexAction a) -> LexAction a+lexer cont = cont =<< lexer'++lexer' :: LexAction Token+lexer' = do+ resetLexeme+ alex <- getAlex+ let startCode = scActual . aiStartCode $ alex+ normaliseStartCode+ newAlex' <- getAlex+ version <- getVersion+ paranthesesCount <- getParanthesesCount+ let user = User version paranthesesCount+ case alexScanUser user newAlex' startCode of+ AlexEOF -> return $ TEOF $ SrcSpan (getPos alex) (getPos alex)+ AlexError _ -> do+ parseState <- get+ fail $ psFilename parseState ++ ": lexing failed. "+#ifdef DEBUG+ ++ '\n' : show newAlex ++ "\n"+#endif+ AlexSkip newAlex _ -> do+ putAlex $ newAlex { aiStartCode = StartCode startCode Return }+ lexer'+ AlexToken newAlex _ action -> do+ putAlex newAlex+ maybeToken <- action+ case maybeToken of+ Just token -> do+ updatePreviousToken maybeToken+ addToPreviousTokensInLine token+ return token+ Nothing -> lexer'++alexScanUser :: User -> AlexInput -> Int -> AlexReturn (LexAction (Maybe Token))++--------------------------------------------------------------------------------+-- Tokens+--------------------------------------------------------------------------------++data Token =+ TId SrcSpan String+ | TComment SrcSpan String+ | TString SrcSpan String+ | TIntegerLiteral SrcSpan String+ | TRealLiteral SrcSpan RealLit+ | TBozLiteral SrcSpan Boz+ | TComma SrcSpan+ | TComma2 SrcSpan+ | TSemiColon SrcSpan+ | TColon SrcSpan+ | TDoubleColon SrcSpan+ | TOpAssign SrcSpan+ | TArrow SrcSpan+ | TPercent SrcSpan+ | TLeftPar SrcSpan+ | TLeftPar2 SrcSpan+ | TRightPar SrcSpan+ | TLeftInitPar SrcSpan+ | TRightInitPar SrcSpan+ -- Mainly operators+ | TOpCustom SrcSpan String+ | TOpExp SrcSpan+ | TOpPlus SrcSpan+ | TOpMinus SrcSpan+ | TStar SrcSpan+ | TOpDivision SrcSpan+ | TSlash SrcSpan+ | TOpOr SrcSpan+ | TOpAnd SrcSpan+ | TOpNot SrcSpan+ | TOpEquivalent SrcSpan+ | TOpNotEquivalent SrcSpan+ | TOpLT SrcSpan+ | TOpLE SrcSpan+ | TOpEQ SrcSpan+ | TOpNE SrcSpan+ | TOpGT SrcSpan+ | TOpGE SrcSpan+ | TLogicalLiteral SrcSpan Bool+ | TUnderscore SrcSpan+ -- Keywords+ -- Program unit related+ | TProgram SrcSpan+ | TEndProgram SrcSpan+ | TFunction SrcSpan+ | TEndFunction SrcSpan+ | TResult SrcSpan+ | TPure SrcSpan+ | TElemental SrcSpan+ | TRecursive SrcSpan+ | TSubroutine SrcSpan+ | TEndSubroutine SrcSpan+ | TBlockData SrcSpan+ | TEndBlockData SrcSpan+ | TModule SrcSpan+ | TEndModule SrcSpan+ | TContains SrcSpan+ | TUse SrcSpan+ | TOnly SrcSpan+ | TImport SrcSpan+ | TAbstract SrcSpan+ | TInterface SrcSpan+ | TEndInterface SrcSpan+ | TProcedure SrcSpan+ | TModuleProcedure SrcSpan+ | TAssignment SrcSpan+ | TOperator SrcSpan+ | TCall SrcSpan+ | TReturn SrcSpan+ | TEntry SrcSpan+ | TInclude SrcSpan+ -- language-binding-spec+ | TBind SrcSpan+ | TC SrcSpan+ | TName SrcSpan+ -- Attributes+ | TAllocatable SrcSpan+ | TAsynchronous SrcSpan+ | TDimension SrcSpan+ | TExternal SrcSpan+ | TIntent SrcSpan+ | TIntrinsic SrcSpan+ | TNonIntrinsic SrcSpan+ | TOptional SrcSpan+ | TParameter SrcSpan+ | TPointer SrcSpan+ | TPrivate SrcSpan+ | TPublic SrcSpan+ | TProtected SrcSpan+ | TSave SrcSpan+ | TTarget SrcSpan+ | TValue SrcSpan+ | TVolatile SrcSpan+ -- Attribute values+ | TIn SrcSpan+ | TOut SrcSpan+ | TInOut SrcSpan+ -- Beginning keyword+ | TData SrcSpan+ | TNamelist SrcSpan+ | TImplicit SrcSpan+ | TEquivalence SrcSpan+ | TCommon SrcSpan+ | TFormat SrcSpan+ | TBlob SrcSpan String+ | TAllocate SrcSpan+ | TStat SrcSpan+ | TErrMsg SrcSpan+ | TSource SrcSpan+ | TDeallocate SrcSpan+ | TNullify SrcSpan+ -- Misc+ | TNone SrcSpan+ -- Control flow+ | TGoto SrcSpan+ | TAssign SrcSpan+ | TTo SrcSpan+ | TContinue SrcSpan+ | TStop SrcSpan+ | TPause SrcSpan+ | TDo SrcSpan+ | TEndDo SrcSpan+ | TWhile SrcSpan+ | TIf SrcSpan+ | TThen SrcSpan+ | TElse SrcSpan+ | TElsif SrcSpan+ | TEndIf SrcSpan+ | TCase SrcSpan+ | TSelectCase SrcSpan+ | TEndSelect SrcSpan+ | TDefault SrcSpan+ | TCycle SrcSpan+ | TExit SrcSpan+ | TForall SrcSpan+ | TEndForall SrcSpan+ | TAssociate SrcSpan+ | TEndAssociate SrcSpan+ -- Where construct+ | TWhere SrcSpan+ | TElsewhere SrcSpan+ | TEndWhere SrcSpan+ -- Type related+ | TType SrcSpan+ | TEndType SrcSpan+ | TSequence SrcSpan+ | TClass SrcSpan+ | TEnum SrcSpan+ | TEnumerator SrcSpan+ | TEndEnum SrcSpan+ -- Selector+ | TKind SrcSpan+ | TLen SrcSpan+ -- Intrinsic types+ | TInteger SrcSpan+ | TReal SrcSpan+ | TDoublePrecision SrcSpan+ | TLogical SrcSpan+ | TCharacter SrcSpan+ | TComplex SrcSpan+ -- I/O+ | TOpen SrcSpan+ | TClose SrcSpan+ | TRead SrcSpan+ | TWrite SrcSpan+ | TPrint SrcSpan+ | TBackspace SrcSpan+ | TRewind SrcSpan+ | TInquire SrcSpan+ | TEndfile SrcSpan+ -- Etc.+ | TEnd SrcSpan+ | TNewline SrcSpan+ | TEOF SrcSpan+ | TFlush SrcSpan+ | TUnit SrcSpan+ | TIOStat SrcSpan+ | TIOMsg SrcSpan+ | TErr SrcSpan+ deriving (Eq, Show, Data, Typeable, Generic)++instance FirstParameter Token SrcSpan+instance FirstParameter Token SrcSpan => Spanned Token where+ getSpan = getFirstParameter+ setSpan = setFirstParameter++instance Tok Token where+ eofToken TEOF{} = True+ eofToken _ = False++class SpecifiesType a where+ isTypeSpec :: a -> Bool++instance SpecifiesType Token where+ isTypeSpec TInteger{} = True+ isTypeSpec TReal{} = True+ isTypeSpec TDoublePrecision{} = True+ isTypeSpec TLogical{} = True+ isTypeSpec TCharacter{} = True+ isTypeSpec TComplex{} = True+ isTypeSpec _ = False++instance SpecifiesType [ Token ] where+ isTypeSpec tokens+ | [ TType{}, TLeftPar{}, _, TRightPar{} ] <- tokens = True+ -- This is an approximation but should hold for almost all legal programs.+ | (typeToken:TLeftPar{}:rest) <- tokens =+ isTypeSpec typeToken &&+ case last rest of+ TRightPar{} -> True+ _ -> False+ | (TCharacter{}:TStar{}:rest) <- tokens =+ case rest of+ [ TIntegerLiteral{} ] -> True+ (TLeftPar{}:rest') | TRightPar{} <- last rest' -> True+ _ -> False+ | otherwise = False++}
+ src/Language/Fortran/Parser/Free/Utils.hs view
@@ -0,0 +1,23 @@+{-# LANGUAGE CPP #-}+module Language.Fortran.Parser.Free.Utils where++import Language.Fortran.Parser.Free.Lexer+import Language.Fortran.Parser.Monad+import Control.Monad.State++unitNameCheck :: Token -> String -> Parse AlexInput Token ()+unitNameCheck (TId _ name1) name2+ | name1 == name2 = return ()+ | otherwise = fail "Unit name does not match the corresponding END statement."+unitNameCheck _ _ = return ()++parseError :: Token -> LexAction a+parseError _ = do+ parseState <- get+#ifdef DEBUG+ tokens <- reverse <$> aiPreviousTokensInLine <$> getAlex+#endif+ fail $ psFilename parseState ++ ": parsing failed. "+#ifdef DEBUG+ ++ '\n' : show tokens+#endif
+ src/Language/Fortran/Parser/LexerUtils.hs view
@@ -0,0 +1,18 @@+{-| Utils for both lexers. -}+module Language.Fortran.Parser.LexerUtils ( readIntOrBoz ) where++import Language.Fortran.AST.Boz+import Numeric++-- | Read a string as either a signed integer, or a BOZ constant (positive).+--+-- Useful in manual lexing.+readIntOrBoz :: String -> Integer+readIntOrBoz s = do+ case readSToMaybe $ readSigned readDec s of+ Just int -> int+ Nothing -> bozAsNatural $ parseBoz s++readSToMaybe :: [(a, b)] -> Maybe a+readSToMaybe = \case (x, _):_ -> Just x+ _ -> Nothing
+ src/Language/Fortran/Parser/Monad.hs view
@@ -0,0 +1,224 @@+{-| Parser/lexer monad, plus common functionality and definitions. -}++{-# LANGUAGE UndecidableInstances #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE FunctionalDependencies #-}+{-# LANGUAGE CPP #-}++module Language.Fortran.Parser.Monad where++#if !MIN_VERSION_base(4,13,0)+-- Control.Monad.Fail import is redundant since GHC 8.8.1+import qualified Control.Monad.Fail as Fail+import Control.Monad.Fail (MonadFail)+#endif++import Language.Fortran.Version+import Language.Fortran.Util.Position++import Control.Exception+import GHC.IO.Exception ( IOException(..), IOErrorType(..) )+import Control.Monad.State hiding (state)+import Control.Monad.Except+import Data.Typeable++-------------------------------------------------------------------------------+-- Helper datatype definitions+-------------------------------------------------------------------------------++data ParanthesesCount = ParanthesesCount+ { pcActual :: Integer+ , pcHasReached0 :: Bool }+ deriving (Show, Eq)++data Context =+ ConStart+ | ConData+ | ConImplicit+ | ConNamelist+ | ConCommon+ deriving (Show, Eq)++data ParseState a = ParseState+ { psAlexInput :: a+ , psParanthesesCount :: ParanthesesCount+ , psVersion :: FortranVersion -- To differentiate lexing behaviour+ , psFilename :: String -- To save correct source location in AST+ , psContext :: [ Context ]+ }+ deriving (Show)++data ParseError a b = ParseError+ { errPos :: Position+ , errLastToken :: Maybe b+ , errFilename :: String+ , errMsg :: String }++instance Show b => Show (ParseError a b) where+ show err = show (errPos err) ++ ": " ++ errMsg err ++ lastTokenMsg+ where lastTokenMsg = tokenMsg (errLastToken err)++tokenMsg :: Show a => Maybe a -> String+tokenMsg (Just a) = "Last parsed token: " ++ show a ++ "."+tokenMsg Nothing = "No token had been lexed."++data ParseResult b c a = ParseOk a (ParseState b) | ParseFailed (ParseError b c)+ deriving stock (Functor)++instance (Typeable a, Typeable b, Show a, Show b) => Exception (ParseError a b)++-- Provides a way to aggregate errors that come+-- from parses with different token types+data ParseErrorSimple = ParseErrorSimple+ { errorPos :: Position+ , errorFilename :: String+ , errorMsg :: String+ } deriving (Exception)++instance Show ParseErrorSimple where+ show err = errorFilename err ++ ", " ++ show (errorPos err) ++ ": " ++ errorMsg err++class LastToken a b | a -> b where+ getLastToken :: (Show b) => a -> Maybe b++class Tok a where+ eofToken :: a -> Bool++-------------------------------------------------------------------------------+-- Parser Monad definition+-------------------------------------------------------------------------------++newtype Parse b c a = Parse { unParse :: ParseState b -> ParseResult b c a }++instance (Loc b, LastToken b c, Show c) => Monad (Parse b c) where+ return a = Parse $ \s -> ParseOk a s++ (Parse m) >>= f = Parse $ \s ->+ case m s of+ ParseOk a s' -> unParse (f a) s'+ ParseFailed e -> ParseFailed e++#if !MIN_VERSION_base(4,13,0)+ -- Monad(fail) was removed in GHC 8.8.1+ fail = Fail.fail+#endif++instance (Loc b, LastToken b c, Show c) => MonadFail (Parse b c) where+ fail msg = Parse $ \s -> ParseFailed ParseError+ { errPos = (getPos . psAlexInput) s+ , errLastToken = (getLastToken . psAlexInput) s+ , errFilename = psFilename s+ , errMsg = msg }++instance (Loc b, LastToken b c, Show c) => Functor (Parse b c) where+ fmap = liftM++instance (Loc b, LastToken b c, Show c) => Applicative (Parse b c) where+ pure = return+ (<*>) = ap++instance (Loc b, LastToken b c, Show c) => MonadState (ParseState b) (Parse b c) where+ get = Parse $ \s -> ParseOk s s+ put s = Parse $ \_ -> ParseOk () s++instance (Loc b, LastToken b c, Show c) => MonadError (ParseError b c) (Parse b c) where+ throwError e = Parse $ \_ -> ParseFailed e++ (Parse m) `catchError` f = Parse $ \s ->+ case m s of+ ParseFailed e -> unParse (f e) s+ m' -> m'+++runParse+ :: (Loc b, LastToken b c, Show c)+ => Parse b c a -> ParseState b -> ParseResult b c a+runParse = unParse++runParseUnsafe+ :: (Loc b, LastToken b c, Show c)+ => Parse b c a -> ParseState b -> (a, ParseState b)+runParseUnsafe lexer initState =+ case unParse lexer initState of+ ParseOk a s -> (a, s)+ ParseFailed e -> throwIOError $ show e++throwIOError :: String -> a+throwIOError s = throw+ IOError { ioe_handle = Nothing+ , ioe_type = UserError+ , ioe_location = "fortran-src"+ , ioe_description = s+ , ioe_errno = Nothing+ , ioe_filename = Nothing }++evalParse+ :: (Loc b, LastToken b c, Show c)+ => Parse b c a -> ParseState b -> a+evalParse m s = fst (runParseUnsafe m s)++execParse+ :: (Loc b, LastToken b c, Show c)+ => Parse b c a -> ParseState b -> ParseState b+execParse m s = snd (runParseUnsafe m s)++-------------------------------------------------------------------------------+-- Parser helper functions+-------------------------------------------------------------------------------++getVersion :: (Loc a, LastToken a b, Show b) => Parse a b FortranVersion+getVersion = do+ s <- get+ return (psVersion s)++putAlex :: (Loc a, LastToken a b, Show b) => a -> Parse a b ()+putAlex ai = do+ s <- get+ put (s { psAlexInput = ai })++getAlex :: (Loc a, LastToken a b, Show b) => Parse a b a+getAlex = do+ s <- get+ return (psAlexInput s)++topContext :: (Loc a, LastToken a b, Show b) => Parse a b Context+topContext = head . psContext <$> get++popContext :: (Loc a, LastToken a b, Show b) => Parse a b ()+popContext = modify $ \ps -> ps { psContext = tail $ psContext ps }++pushContext :: (Loc a, LastToken a b, Show b) => Context -> Parse a b ()+pushContext context = modify $ \ps -> ps { psContext = context : psContext ps }++getPosition :: (Loc a, LastToken a b, Show b) => Parse a b Position+getPosition = do+ parseState <- get+ return $ getPos $ psAlexInput parseState++getSrcSpan :: (Loc a, LastToken a b, Show b) => Position -> Parse a b SrcSpan+getSrcSpan loc1 = do+ loc2 <- getPosition+ return $ SrcSpan loc1 loc2++getParanthesesCount :: (Loc a, LastToken a b, Show b) => Parse a b ParanthesesCount+getParanthesesCount = psParanthesesCount <$> get++resetPar :: (Loc a, LastToken a b, Show b) => Parse a b ()+resetPar = do+ ps <- get+ put $ ps { psParanthesesCount = ParanthesesCount 0 False }++incPar :: (Loc a, LastToken a b, Show b) => Parse a b ()+incPar = do+ ps <- get+ let pc = psParanthesesCount ps+ let count = pcActual pc+ put $ ps { psParanthesesCount = pc { pcActual = count + 1 } }++decPar :: (Loc a, LastToken a b, Show b) => Parse a b ()+decPar = do+ ps <- get+ let pc = psParanthesesCount ps+ let newCount = pcActual pc - 1+ let reached0 = pcHasReached0 pc || newCount == 0+ put $ ps { psParanthesesCount = ParanthesesCount newCount reached0 }
− src/Language/Fortran/Parser/Utils.hs
@@ -1,47 +0,0 @@-{-| Simple module to provide functions that read Fortran literals -}-module Language.Fortran.Parser.Utils- ( readReal- , readInteger- ) where--import Data.Char-import Numeric--breakAtDot :: String -> (String, String)-replaceDwithE :: Char -> Char-readsToMaybe :: [(a, b)] -> Maybe a-fixAtDot :: (String, String) -> (String, String)-fixAtDot' :: (String, String) -> (String, String)-combineAtDot :: (String, String) -> String---- | Convert a Fortran literal Real into a Haskell Double.-readReal :: String -> Maybe Double-readReal = readsToMaybe . reads . filter (/= '+') . combineAtDot . fixAtDot . breakAtDot . map replaceDwithE . takeWhile (/= '_')---- | Convert a Fortran literal Integer into a Haskell Integer.-readInteger :: String -> Maybe Integer-readInteger s = readsToMaybe $ case s' of- 'b':_ -> readInt 2 (`elem` "01") digitToInt (drop 2 s')- 'o':_ -> readInt 8 (`elem` ['0'..'7']) digitToInt (drop 2 s')- 'z':_ -> readInt 16 (`elem` (['0'..'9'] ++ ['A'..'F'] ++ ['a'..'f'])) digitToInt (drop 2 s')- _ -> readSigned readDec s'- where- s' = filter (/= '+') . takeWhile (/= '_') $ s--fixAtDot' ("", r) = ("0", r)-fixAtDot' ("-", r) = ("-0", r)-fixAtDot' (l, "") = (l, "0")-fixAtDot' (l, r0:r) | not (isDigit r0) = (l, '0':r0:r)-fixAtDot' x = x--combineAtDot (a, b) = a ++ "." ++ b-fixAtDot x- | x == x' = x- | otherwise = fixAtDot x' where x' = fixAtDot' x-breakAtDot = fmap (drop 1) . break (=='.')-replaceDwithE 'd' = 'e'-replaceDwithE c = c--readsToMaybe r = case r of- (x, _):_ -> Just x- _ -> Nothing
− src/Language/Fortran/ParserMonad.hs
@@ -1,276 +0,0 @@-{-# LANGUAGE DeriveGeneric #-}-{-# LANGUAGE DeriveDataTypeable #-}-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE UndecidableInstances #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE FunctionalDependencies #-}-{-# LANGUAGE CPP #-}--module Language.Fortran.ParserMonad- ( module Language.Fortran.ParserMonad- , module Language.Fortran.Version -- TODO: temporary plug to avoid API change- ) where--#if !MIN_VERSION_base(4,13,0)--- Control.Monad.Fail import is redundant since GHC 8.8.1-import qualified Control.Monad.Fail as Fail-import Control.Monad.Fail (MonadFail)-#endif--import Language.Fortran.Version--import GHC.IO.Exception-import Control.Exception--import Control.Monad.State hiding (state)-import Control.Monad.Except--import Data.Typeable-import Language.Fortran.Util.Position------------------------------------------------------------------------------------ Helper datatype definitions----------------------------------------------------------------------------------data ParanthesesCount = ParanthesesCount- { pcActual :: Integer- , pcHasReached0 :: Bool }- deriving (Show, Eq)--data Context =- ConStart- | ConData- | ConImplicit- | ConNamelist- | ConCommon- deriving (Show, Eq)--data ParseState a = ParseState- { psAlexInput :: a- , psParanthesesCount :: ParanthesesCount- , psVersion :: FortranVersion -- To differentiate lexing behaviour- , psFilename :: String -- To save correct source location in AST- , psContext :: [ Context ]- }- deriving (Show)--data ParseError a b = ParseError- { errPos :: Position- , errLastToken :: Maybe b- , errFilename :: String- , errMsg :: String }---instance Show b => Show (ParseError a b) where- show err = show (errPos err) ++ ": " ++ errMsg err ++ lastTokenMsg- where- lastTokenMsg = tokenMsg (errLastToken err)--tokenMsg :: Show a => Maybe a -> String-tokenMsg (Just a) = "Last parsed token: " ++ show a ++ "."-tokenMsg Nothing = "No token had been lexed."--instance Functor (ParseResult b c) where- fmap f (ParseOk a s) = ParseOk (f a) s- fmap _ (ParseFailed err) = ParseFailed err--instance (Typeable a, Typeable b, Show a, Show b) => Exception (ParseError a b)--data ParseResult b c a = ParseOk a (ParseState b) | ParseFailed (ParseError b c)---- Provides a way to aggregate errors that come--- from parses with different token types-data ParseErrorSimple = ParseErrorSimple- { errorPos :: Position- , errorFilename :: String- , errorMsg :: String }--fromParseResultUnsafe :: (Show c) => ParseResult b c a -> a-fromParseResultUnsafe (ParseOk a _) = a-fromParseResultUnsafe (ParseFailed err) = throwIOerror $ show err--fromRight :: Show a => Either a b -> b-fromRight (Left x) = throwIOerror . show $ x-fromRight (Right x) = x--fromParseResult :: (Show c) => ParseResult b c a -> Either ParseErrorSimple a-fromParseResult (ParseOk a _) = Right a-fromParseResult (ParseFailed err) =- Left ParseErrorSimple- { errorPos = errPos err- , errorFilename = errFilename err- , errorMsg = errMsg err ++ "\n" ++ tokenMsg (errLastToken err) }--instance Show ParseErrorSimple where- show err = errorFilename err ++ ", " ++ show (errorPos err) ++ ": " ++ errorMsg err--class LastToken a b | a -> b where- getLastToken :: (Show b) => a -> Maybe b------------------------------------------------------------------------------------ Parser Monad definition----------------------------------------------------------------------------------newtype Parse b c a = Parse { unParse :: ParseState b -> ParseResult b c a }--instance (Loc b, LastToken b c, Show c) => Monad (Parse b c) where- return a = Parse $ \s -> ParseOk a s-- (Parse m) >>= f = Parse $ \s ->- case m s of- ParseOk a s' -> unParse (f a) s'- ParseFailed e -> ParseFailed e--#if !MIN_VERSION_base(4,13,0)- -- Monad(fail) was removed in GHC 8.8.1- fail = Fail.fail-#endif--instance (Loc b, LastToken b c, Show c) => MonadFail (Parse b c) where- fail msg = Parse $ \s -> ParseFailed ParseError- { errPos = (getPos . psAlexInput) s- , errLastToken = (getLastToken . psAlexInput) s- , errFilename = psFilename s- , errMsg = msg }--instance (Loc b, LastToken b c, Show c) => Functor (Parse b c) where- fmap = liftM--instance (Loc b, LastToken b c, Show c) => Applicative (Parse b c) where- pure = return- (<*>) = ap--instance (Loc b, LastToken b c, Show c) => MonadState (ParseState b) (Parse b c) where- get = Parse $ \s -> ParseOk s s- put s = Parse $ \_ -> ParseOk () s--instance (Loc b, LastToken b c, Show c) => MonadError (ParseError b c) (Parse b c) where- throwError e = Parse $ \_ -> ParseFailed e-- (Parse m) `catchError` f = Parse $ \s ->- case m s of- ParseFailed e -> unParse (f e) s- m' -> m'------------------------------------------------------------------------------------ Parser helper functions----------------------------------------------------------------------------------getVersion :: (Loc a, LastToken a b, Show b) => Parse a b FortranVersion-getVersion = do- s <- get- return (psVersion s)--putAlex :: (Loc a, LastToken a b, Show b) => a -> Parse a b ()-putAlex ai = do- s <- get- put (s { psAlexInput = ai })--getAlex :: (Loc a, LastToken a b, Show b) => Parse a b a-getAlex = do- s <- get- return (psAlexInput s)--topContext :: (Loc a, LastToken a b, Show b) => Parse a b Context-topContext = head . psContext <$> get--popContext :: (Loc a, LastToken a b, Show b) => Parse a b ()-popContext = modify $ \ps -> ps { psContext = tail $ psContext ps }--pushContext :: (Loc a, LastToken a b, Show b) => Context -> Parse a b ()-pushContext context = modify $ \ps -> ps { psContext = context : psContext ps }--getPosition :: (Loc a, LastToken a b, Show b) => Parse a b Position-getPosition = do- parseState <- get- return $ getPos $ psAlexInput parseState--getSrcSpan :: (Loc a, LastToken a b, Show b) => Position -> Parse a b SrcSpan-getSrcSpan loc1 = do- loc2 <- getPosition- return $ SrcSpan loc1 loc2--getParanthesesCount :: (Loc a, LastToken a b, Show b) => Parse a b ParanthesesCount-getParanthesesCount = psParanthesesCount <$> get--resetPar :: (Loc a, LastToken a b, Show b) => Parse a b ()-resetPar = do- ps <- get- put $ ps { psParanthesesCount = ParanthesesCount 0 False }--incPar :: (Loc a, LastToken a b, Show b) => Parse a b ()-incPar = do- ps <- get- let pc = psParanthesesCount ps- let count = pcActual pc- put $ ps { psParanthesesCount = pc { pcActual = count + 1 } }--decPar :: (Loc a, LastToken a b, Show b) => Parse a b ()-decPar = do- ps <- get- let pc = psParanthesesCount ps- let newCount = pcActual pc - 1- let reached0 = pcHasReached0 pc || newCount == 0- put $ ps { psParanthesesCount = ParanthesesCount newCount reached0 }------------------------------------------------------------------------------------ Generic token collection and functions----------------------------------------------------------------------------------throwIOerror :: String -> a-throwIOerror s = throw- IOError { ioe_handle = Nothing- , ioe_type = UserError- , ioe_location = "fortran-src"- , ioe_description = s- , ioe_errno = Nothing- , ioe_filename = Nothing }--runParse :: (Loc b, LastToken b c, Show c) => Parse b c a -> ParseState b -> ParseResult b c a-runParse = unParse--runParseUnsafe :: (Loc b, LastToken b c, Show c) => Parse b c a -> ParseState b -> (a, ParseState b)-runParseUnsafe lexer initState =- case unParse lexer initState of- ParseOk a s -> (a, s)- ParseFailed e -> throwIOerror $ show e--evalParse :: (Loc b, LastToken b c, Show c) => Parse b c a -> ParseState b -> a-evalParse m s = fst (runParseUnsafe m s)--execParse :: (Loc b, LastToken b c, Show c) => Parse b c a -> ParseState b -> ParseState b-execParse m s = snd (runParseUnsafe m s)--class Tok a where- eofToken :: a -> Bool--collectTokens :: forall a b . (Loc b, Tok a, LastToken b a, Show a) => Parse b a a -> ParseState b -> [a]-collectTokens lexer initState =- evalParse (_collectTokens initState) undefined- where- _collectTokens :: (Loc b, Tok a, LastToken b a, Show a) => ParseState b -> Parse b a [a]- _collectTokens state = do- let (_token, _state) = runParseUnsafe lexer state- if eofToken _token- then return [_token]- else do- _tokens <- _collectTokens _state- return $ _token:_tokens--collectTokensSafe :: forall a b . (Loc b, Tok a, LastToken b a, Show a) => Parse b a a -> ParseState b -> Maybe [a]-collectTokensSafe lexer initState =- evalParse (_collectTokens initState) undefined- where- _collectTokens :: (Loc b, Tok a, LastToken b a, Show a) => ParseState b -> Parse b a (Maybe [a])- _collectTokens state =- case unParse lexer state of- ParseOk _token _state ->- if eofToken _token- then return $ Just [_token]- else do- _mTokens <- _collectTokens _state- case _mTokens of- Just _tokens -> return $ Just $ _token:_tokens- _ -> return Nothing- _ -> return Nothing
src/Language/Fortran/PrettyPrint.hs view
@@ -1,6 +1,3 @@-{-# LANGUAGE LambdaCase #-}-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE UndecidableInstances #-} {-# OPTIONS_GHC -Wno-orphans #-}@@ -804,6 +801,11 @@ case key of Just keyName -> text keyName <+> char '=' <+> pprint' v e Nothing -> pprint' v e++instance Pretty (ArgumentExpression a) where+ pprint' v = \case+ ArgExpr e -> pprint' v e+ ArgExprVar _ _ var -> "(" <> pprint' v var <> ")" instance Pretty (Attribute a) where pprint' v attr
src/Language/Fortran/Transformation/Disambiguation/Function.hs view
@@ -1,5 +1,4 @@ {-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE PatternGuards #-} module Language.Fortran.Transformation.Disambiguation.Function (disambiguateFunction) where @@ -9,7 +8,7 @@ import Language.Fortran.Analysis import Language.Fortran.AST-import Language.Fortran.Transformation.TransformMonad+import Language.Fortran.Transformation.Monad disambiguateFunction :: Data a => Transform a ()@@ -60,7 +59,7 @@ fromIndex :: Index b -> a b instance Indexed Argument where- fromIndex (IxSingle a s mKey e) = Argument a s mKey e+ fromIndex (IxSingle a s mKey e) = Argument a s mKey (ArgExpr e) fromIndex IxRange{} = error "Deduced a function but argument is not an expression."
src/Language/Fortran/Transformation/Disambiguation/Intrinsic.hs view
@@ -1,5 +1,4 @@ {-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE PatternGuards #-} module Language.Fortran.Transformation.Disambiguation.Intrinsic (disambiguateIntrinsic) where @@ -9,7 +8,7 @@ import Language.Fortran.Analysis import Language.Fortran.AST-import Language.Fortran.Transformation.TransformMonad+import Language.Fortran.Transformation.Monad disambiguateIntrinsic :: Data a => Transform a ()
src/Language/Fortran/Transformation/Grouping.hs view
@@ -1,3 +1,7 @@+{-|+Note that labeled (nonblock) DO grouping must be done before block DO grouping.+-}+ module Language.Fortran.Transformation.Grouping ( groupForall , groupDo , groupLabeledDo@@ -6,7 +10,7 @@ import Language.Fortran.AST import Language.Fortran.Util.Position import Language.Fortran.Analysis-import Language.Fortran.Transformation.TransformMonad+import Language.Fortran.Transformation.Monad import Data.Data import Data.List (intercalate)
+ src/Language/Fortran/Transformation/Monad.hs view
@@ -0,0 +1,42 @@+module Language.Fortran.Transformation.Monad+ ( getProgramFile+ , putProgramFile+ , modifyProgramFile+ , runTransform+ , Transform+ ) where++import Prelude hiding (lookup)+import Control.Monad.State.Lazy hiding (state)+import Data.Data++import Language.Fortran.Analysis+import Language.Fortran.Analysis.Types+import Language.Fortran.Analysis.Renaming+import Language.Fortran.AST (ProgramFile)++data TransformationState a = TransformationState+ { transProgramFile :: ProgramFile (Analysis a) }++type Transform a = State (TransformationState a)++runTransform+ :: Data a+ => TypeEnv -> ModuleMap -> Transform a () -> ProgramFile a -> ProgramFile a+runTransform env mmap trans pf =+ stripAnalysis . transProgramFile . execState trans $ initState+ where+ (pf', _) = analyseTypesWithEnv env . analyseRenamesWithModuleMap mmap . initAnalysis $ pf+ initState = TransformationState+ { transProgramFile = pf' }++getProgramFile :: Transform a (ProgramFile (Analysis a))+getProgramFile = gets transProgramFile++putProgramFile :: ProgramFile (Analysis a) -> Transform a ()+putProgramFile pf = do+ state <- get+ put $ state { transProgramFile = pf }++modifyProgramFile :: (ProgramFile (Analysis a) -> ProgramFile (Analysis a)) -> Transform a ()+modifyProgramFile f = modify $ \ s -> s { transProgramFile = f (transProgramFile s) }
− src/Language/Fortran/Transformation/TransformMonad.hs
@@ -1,40 +0,0 @@-module Language.Fortran.Transformation.TransformMonad- ( getProgramFile- , putProgramFile- , modifyProgramFile- , runTransform- , Transform)--where--import Prelude hiding (lookup)-import Control.Monad.State.Lazy hiding (state)-import Data.Data--import Language.Fortran.Analysis-import Language.Fortran.Analysis.Types-import Language.Fortran.Analysis.Renaming-import Language.Fortran.AST (ProgramFile)--data TransformationState a = TransformationState- { transProgramFile :: ProgramFile (Analysis a) }--type Transform a = State (TransformationState a)--runTransform :: Data a => TypeEnv -> ModuleMap -> Transform a () -> ProgramFile a -> ProgramFile a-runTransform env mmap trans pf = stripAnalysis . transProgramFile . execState trans $ initState- where- (pf', _) = analyseTypesWithEnv env . analyseRenamesWithModuleMap mmap . initAnalysis $ pf- initState = TransformationState- { transProgramFile = pf' }--getProgramFile :: Transform a (ProgramFile (Analysis a))-getProgramFile = gets transProgramFile--putProgramFile :: ProgramFile (Analysis a) -> Transform a ()-putProgramFile pf = do- state <- get- put $ state { transProgramFile = pf }--modifyProgramFile :: (ProgramFile (Analysis a) -> ProgramFile (Analysis a)) -> Transform a ()-modifyProgramFile f = modify $ \ s -> s { transProgramFile = f (transProgramFile s) }
− src/Language/Fortran/Transformer.hs
@@ -1,70 +0,0 @@-{-# LANGUAGE LambdaCase #-}--module Language.Fortran.Transformer- ( transform- , transformWithModFiles- , Transformation(..)- , defaultTransformations- ) where--import Data.Map (empty)-import Data.Data--import Language.Fortran.Util.ModFile-import Language.Fortran.Transformation.TransformMonad (Transform, runTransform)-import Language.Fortran.Transformation.Disambiguation.Function-import Language.Fortran.Transformation.Disambiguation.Intrinsic-import Language.Fortran.Transformation.Grouping-import Language.Fortran.AST (ProgramFile)-import Language.Fortran.Version (FortranVersion(..))--data Transformation =- GroupForall- | GroupDo- | GroupLabeledDo- | DisambiguateFunction- | DisambiguateIntrinsic- deriving (Eq)--transformationMapping :: Data a => Transformation -> Transform a ()-transformationMapping = \case- GroupForall -> groupForall- 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_ transformationMapping trs--transform :: Data a => [ Transformation ] -> ProgramFile a -> ProgramFile a-transform trs = runTransform empty empty trans- where- trans = mapM_ transformationMapping trs---- | The default post-parse AST transformations for each Fortran version.------ Note that some of these may not be commutative with each other. Specifically,--- the DO groupings are written so labeled (nonblock) DO grouping must occur--- first, followed by block DO grouping.-defaultTransformations :: FortranVersion -> [Transformation]-defaultTransformations = \case- Fortran66 ->- [ GroupLabeledDo- , DisambiguateIntrinsic- , DisambiguateFunction- ]- Fortran77 -> defaultTransformations Fortran66- Fortran77Legacy ->- [ GroupLabeledDo- , GroupDo- , DisambiguateIntrinsic- , DisambiguateFunction- ]- Fortran77Extended -> defaultTransformations Fortran77Legacy- Fortran90 -> defaultTransformations Fortran77Extended- Fortran95 -> defaultTransformations Fortran77Extended- Fortran2003 -> defaultTransformations Fortran77Extended- Fortran2008 -> defaultTransformations Fortran2003
src/Language/Fortran/Util/FirstParameter.hs view
@@ -1,7 +1,5 @@ {-# LANGUAGE DefaultSignatures #-} {-# LANGUAGE TypeOperators #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE FunctionalDependencies #-} module Language.Fortran.Util.FirstParameter(FirstParameter(..), GFirstParameter(..)) where
src/Language/Fortran/Util/ModFile.hs view
@@ -15,10 +15,6 @@ -} {-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE PatternGuards #-}-{-# LANGUAGE TupleSections #-}-{-# LANGUAGE DeriveGeneric #-}-{-# LANGUAGE DeriveDataTypeable #-} {-| @@ -46,15 +42,36 @@ -} module Language.Fortran.Util.ModFile- ( modFileSuffix, ModFile, ModFiles, emptyModFile, emptyModFiles- , lookupModFileData, getLabelsModFileData, alterModFileData -- , alterModFileDataF- , genModFile, regenModFile, encodeModFile, decodeModFile- , StringMap, DeclMap, ParamVarMap, DeclContext(..), extractModuleMap, extractDeclMap- , moduleFilename, combinedStringMap, combinedDeclMap, combinedModuleMap, combinedTypeEnv, combinedParamVarMap+ (+ -- * Main defitions+ ModFile, ModFiles, emptyModFile, emptyModFiles, modFileSuffix+ , lookupModFileData, getLabelsModFileData, alterModFileData, alterModFileDataF++ -- * Creation+ , genModFile, regenModFile++ -- * En/decoding+ , encodeModFile, decodeModFile, decodeModFiles, decodeModFiles'++ -- * Operations+ , moduleFilename+ , StringMap, extractStringMap, combinedStringMap+ , DeclContext(..), DeclMap, extractDeclMap, combinedDeclMap+ , extractModuleMap, combinedModuleMap, combinedTypeEnv+ , ParamVarMap, extractParamVarMap, combinedParamVarMap , genUniqNameToFilenameMap- , TimestampStatus(..), checkTimestamps )-where+ , TimestampStatus(..), checkTimestamps+ ) where +import qualified Language.Fortran.AST as F+import qualified Language.Fortran.Analysis as FA+import qualified Language.Fortran.Analysis.BBlocks as FAB+import qualified Language.Fortran.Analysis.DataFlow as FAD+import qualified Language.Fortran.Analysis.Renaming as FAR+import qualified Language.Fortran.Analysis.Types as FAT+import qualified Language.Fortran.Util.Position as P+import Language.Fortran.Util.Files ( getDirContents )+ import Control.Monad.State import Data.Binary (Binary, encode, decodeOrFail) import qualified Data.ByteString.Lazy.Char8 as LB@@ -63,15 +80,10 @@ import qualified Data.Map.Strict as M import Data.Maybe import GHC.Generics (Generic)-import qualified Language.Fortran.AST as F-import qualified Language.Fortran.Analysis as FA-import qualified Language.Fortran.Analysis.BBlocks as FAB-import qualified Language.Fortran.Analysis.DataFlow as FAD-import qualified Language.Fortran.Analysis.Renaming as FAR-import qualified Language.Fortran.Analysis.Types as FAT-import qualified Language.Fortran.Util.Position as P-import System.Directory-import System.FilePath+import System.Directory ( doesFileExist, getModificationTime )+import qualified System.FilePath+import System.FilePath ( (-<.>), (</>) )+import System.IO ( hPutStrLn, stderr ) -------------------------------------------------- @@ -79,6 +91,11 @@ modFileSuffix :: String modFileSuffix = ".fsmod" +-- | Returns 'true' for filepaths with an extension that identifies them as a+-- mod file.+isModFile :: FilePath -> Bool+isModFile = System.FilePath.isExtensionOf modFileSuffix+ -- | Context of a declaration: the ProgramUnit where it was declared. data DeclContext = DCMain | DCBlockData | DCModule F.ProgramUnitName | DCFunction (F.ProgramUnitName, F.ProgramUnitName) -- ^ (uniqName, srcName)@@ -153,9 +170,12 @@ alterModFileData :: (Maybe LB.ByteString -> Maybe LB.ByteString) -> String -> ModFile -> ModFile alterModFileData f k mf = mf { mfOtherData = M.alter f k . mfOtherData $ mf } --- For when stackage gets containers-0.5.8.1:--- alterModFileDataF :: Functor f => (Maybe B.ByteString -> f (Maybe B.ByteString)) -> String -> ModFile -> f ModFile--- alterModFileDataF f k mf = (\ od -> mf { mfOtherData = od }) <$> M.alterF f k (mfOtherData mf)+alterModFileDataF+ :: Functor f+ => (Maybe LB.ByteString -> f (Maybe LB.ByteString)) -> String -> ModFile+ -> f ModFile+alterModFileDataF f k mf =+ (\od -> mf { mfOtherData = od }) <$> M.alterF f k (mfOtherData mf) -- | Convert ModFiles to a strict ByteString for writing to file. encodeModFile :: [ModFile] -> LB.ByteString@@ -174,6 +194,25 @@ where each mf = (revertStringMap sm mf { mfStringMap = M.empty }) { mfStringMap = sm } where sm = mfStringMap mf++decodeModFiles :: [FilePath] -> IO [(FilePath, ModFile)]+decodeModFiles = foldM (\ modFiles d -> do+ -- Figure out the camfort mod files and parse them.+ modFileNames <- filter isModFile `fmap` getDirContents d+ addedModFiles <- fmap concat . forM modFileNames $ \ modFileName -> do+ contents <- LB.readFile (d </> modFileName)+ case decodeModFile contents of+ Left msg -> do+ hPutStrLn stderr $ modFileName ++ ": Error: " ++ msg+ return [(modFileName, emptyModFile)]+ Right mods -> do+ hPutStrLn stderr $ modFileName ++ ": successfully parsed precompiled file."+ return $ map (modFileName,) mods+ return $ addedModFiles ++ modFiles+ ) [] -- can't use emptyModFiles++decodeModFiles' :: [FilePath] -> IO ModFiles+decodeModFiles' = fmap (map snd) . decodeModFiles -- | Extract the combined module map from a set of ModFiles. Useful -- for parsing a Fortran file in a large context of other modules.
src/Language/Fortran/Util/Position.hs view
@@ -1,9 +1,4 @@-{-# LANGUAGE DeriveDataTypeable #-} {-# LANGUAGE DefaultSignatures #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE DeriveGeneric #-} module Language.Fortran.Util.Position where
src/Language/Fortran/Util/SecondParameter.hs view
@@ -1,7 +1,5 @@ {-# LANGUAGE DefaultSignatures #-} {-# LANGUAGE TypeOperators #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE FunctionalDependencies #-} module Language.Fortran.Util.SecondParameter(SecondParameter(..)) where
src/Language/Fortran/Version.hs view
@@ -1,6 +1,3 @@-{-# LANGUAGE DeriveDataTypeable #-}-{-# LANGUAGE DeriveGeneric #-}- -- | Fortran version enum and tools for selecting version for a given file. module Language.Fortran.Version@@ -8,7 +5,6 @@ , fortranVersionAliases , selectFortranVersion , deduceFortranVersion- , deduceVersion -- deprecated ) where import Data.Char (toLower)@@ -77,7 +73,3 @@ | otherwise = Fortran90 -- unrecognized, default to F90 where isExtensionOf = flip isSuffixOf $ map toLower path---- | Alias for previous function name. TODO: deprecate eventually.-deduceVersion :: FilePath -> FortranVersion-deduceVersion = deduceFortranVersion
− src/Main.hs
@@ -1,482 +0,0 @@-{-# LANGUAGE FlexibleContexts, FlexibleInstances, ScopedTypeVariables, OverloadedStrings #-}-{-# OPTIONS_GHC -Wno-orphans #-}--module Main where--import Prelude hiding (readFile, mod)-import qualified Data.ByteString.Char8 as B-import qualified Data.ByteString.Lazy.Char8 as LB-import Language.Fortran.Util.Files--import Text.PrettyPrint (render)--import System.Console.GetOpt-import System.IO-import System.Environment-import System.Directory-import System.FilePath-import Text.PrettyPrint.GenericPretty (pp, pretty, Out)-import Text.Read (readMaybe)-import Data.List (sortBy, intercalate, isSuffixOf)-import Data.Ord (comparing)-import Data.Char (toLower)-import Data.Maybe (listToMaybe, fromMaybe, maybeToList)-import Data.Data-import Data.Generics.Uniplate.Data--import Language.Fortran.Version (FortranVersion(..), selectFortranVersion, deduceFortranVersion)-import Language.Fortran.ParserMonad (fromRight)-import qualified Language.Fortran.Lexer.FixedForm as FixedForm (collectFixedTokens, Token(..))-import qualified Language.Fortran.Lexer.FreeForm as FreeForm (collectFreeTokens, Token(..))--import Language.Fortran.Parser.Any (parserWithModFilesVersions)--import Language.Fortran.Util.ModFile-import Language.Fortran.Util.Position--import Language.Fortran.PrettyPrint-import Language.Fortran.Analysis-import Language.Fortran.AST-import Language.Fortran.Analysis.Types-import Language.Fortran.Analysis.ModGraph-import Language.Fortran.Analysis.BBlocks-import Language.Fortran.Analysis.DataFlow-import Language.Fortran.Analysis.Renaming-import Data.Graph.Inductive hiding (trc, mf, version)--import qualified Data.IntMap as IM-import qualified Data.Map as M-import Control.Monad-import Text.Printf--programName :: String-programName = "fortran-src"--main :: IO ()-main = do- args <- getArgs- (opts, parsedArgs) <- compileArgs args- case (parsedArgs, action opts) of- (paths, ShowMakeGraph) -> do- paths' <- expandDirs paths- mg <- genModGraph (fortranVersion opts) (includeDirs opts) paths'- putStrLn $ modGraphToDOT mg- -- make: construct a build-dep graph and follow it- (paths, Make) -> do- let mvers = fortranVersion opts- paths' <- expandDirs paths- -- Build the graph of module dependencies- mg0 <- genModGraph mvers (includeDirs opts) paths'- -- Start the list of mods with those from the command line- mods0 <- decodeModFiles $ includeDirs opts- -- Loop through the dependency graph until it is empty- let loop mg mods- | nxt <- takeNextMods mg- , not (null nxt) = do- let fnPaths = [ fn | (_, Just (MOFile fn)) <- nxt ]- newMods <- fmap concat . forM fnPaths $ \ fnPath -> do- tsStatus <- checkTimestamps fnPath- case tsStatus of- NoSuchFile -> do- putStr $ "Does not exist: " ++ fnPath- pure [emptyModFile]- ModFileExists modPath -> do- putStrLn $ "Loading mod file " ++ modPath ++ "."- decodeOneModFile modPath- CompileFile -> do- putStr $ "Summarising " ++ fnPath ++ "..."- mod <- compileFileToMod mvers mods fnPath Nothing- putStrLn "done"- pure [mod]-- let ns = map fst nxt- let mg' = delModNodes ns mg- loop mg' $ newMods ++ mods- loop _ mods = pure mods-- allMods <- loop mg0 mods0- case outputFile opts of- Nothing -> pure ()- Just f -> LB.writeFile f $ encodeModFile allMods-- (paths, Compile) -> do- mods <- decodeModFiles $ includeDirs opts- mapM_ (\ p -> compileFileToMod (fortranVersion opts) mods p (outputFile opts)) paths- (path:_, actionOpt) -> do- contents <- flexReadFile path- let version = fromMaybe (deduceFortranVersion path) (fortranVersion opts)- let parserF0 = parserWithModFilesVersions version- let parserF m b s = fromRight (parserF0 m b s)- let outfmt = outputFormat opts- mods <- decodeModFiles $ includeDirs opts- let mmap = combinedModuleMap mods- let tenv = combinedTypeEnv mods- let pvm = combinedParamVarMap mods-- let runTypes = analyseAndCheckTypesWithEnv tenv . analyseRenamesWithModuleMap mmap . initAnalysis- let runRenamer = stripAnalysis . rename . analyseRenamesWithModuleMap mmap . initAnalysis- let runBBlocks pf = showBBlocks pf' ++ "\n\n" ++ showDataFlow pf'- where pf' = analyseParameterVars pvm . analyseBBlocks . analyseRenamesWithModuleMap mmap . initAnalysis $ pf- let runSuperGraph pf | outfmt == DOT = superBBGrToDOT sgr- | otherwise = superGraphDataFlow pf' sgr- where pf' = analyseParameterVars pvm . analyseBBlocks . analyseRenamesWithModuleMap mmap . initAnalysis $ pf- bbm = genBBlockMap pf'- sgr = genSuperBBGr bbm- let findBlockPU pf astBlockId = listToMaybe- [ pu | pu <- universeBi pf :: [ProgramUnit (Analysis A0)]- , bbgr <- maybeToList (bBlocks (getAnnotation pu))- , b <- concatMap snd $ labNodes (bbgrGr bbgr)- , insLabel (getAnnotation b) == Just astBlockId ]- case actionOpt of- Lex | version `elem` [ Fortran66, Fortran77, Fortran77Extended, Fortran77Legacy ] ->- print $ FixedForm.collectFixedTokens version contents- Lex | version `elem` [Fortran90, Fortran2003, Fortran2008] ->- print $ FreeForm.collectFreeTokens version contents- Lex -> ioError $ userError $ usageInfo programName options- Parse -> pp $ parserF mods contents path- Typecheck -> let (pf, _, errs) = runTypes (parserF mods contents path) in- printTypeErrors errs >> printTypes (extractTypeEnv pf)- Rename -> pp . runRenamer $ parserF mods contents path- BBlocks -> putStrLn . runBBlocks $ parserF mods contents path- SuperGraph -> putStrLn . runSuperGraph $ parserF mods contents path- Reprint ->- let prettyContents = render . flip (pprint version) (Just 0) $ parserF mods contents path- in putStrLn $- if useContinuationReformatter opts- then reformatMixedFormInsertContinuations prettyContents- else prettyContents- DumpModFile -> do- let path' = if modFileSuffix `isSuffixOf` path then path else path <.> modFileSuffix- contents' <- LB.readFile path'- case decodeModFile contents' of- Left msg -> putStrLn $ "Error: " ++ msg- Right mfs -> forM_ mfs $ \ mf ->- putStrLn $ "Filename: " ++ moduleFilename mf ++- "\n\nStringMap:\n" ++ showStringMap (combinedStringMap [mf]) ++- "\n\nModuleMap:\n" ++ showModuleMap (combinedModuleMap [mf]) ++- "\n\nDeclMap:\n" ++ showGenericMap (combinedDeclMap [mf]) ++- "\n\nTypeEnv:\n" ++ showTypes (combinedTypeEnv [mf]) ++- "\n\nParamVarMap:\n" ++ showGenericMap (combinedParamVarMap [mf]) ++- "\n\nOther Data Labels: " ++ show (getLabelsModFileData mf)- ShowFlows isFrom isSuper astBlockId -> do- let pf = analyseParameterVars pvm .- analyseBBlocks .- analyseRenamesWithModuleMap mmap .- initAnalysis $ parserF mods contents path- let bbm = genBBlockMap pf- case (isSuper, findBlockPU pf astBlockId) of- (False, Nothing) -> fail "Couldn't find given AST block ID number."- (False, Just pu)- | Just bbgr <- M.lookup (puName pu) bbm ->- putStrLn $ showFlowsDOT pf bbgr astBlockId isFrom- | otherwise -> do- print $ M.keys bbm- fail $ "Internal error: Program Unit " ++ show (puName pu) ++ " is lacking a basic block graph."- (True, _) -> do- let sgr = genSuperBBGr bbm- putStrLn $ showFlowsDOT pf (superBBGrGraph sgr) astBlockId isFrom- ShowBlocks mlinenum -> do- let pf = analyseBBlocks .- analyseRenamesWithModuleMap mmap .- initAnalysis $ parserF mods contents path- let f :: ([ASTBlockNode], Int) -> ([ASTBlockNode], Int) -> ([ASTBlockNode], Int)- f (nodes1, len1) (nodes2, len2)- | len1 < len2 = (nodes1, len1)- | len2 < len1 = (nodes2, len2)- | otherwise = (nodes1 ++ nodes2, len1)- let lineMap :: IM.IntMap ([ASTBlockNode], Int) -- ([list of IDs], line-distance of span)- lineMap = IM.fromListWith f [- (l, ([i], lineDistance ss))- | b <- universeBi pf :: [Block (Analysis A0)]- , i <- maybeToList . insLabel $ getAnnotation b- , let ss = getSpan b- , l <- spannedLines ss- ]- case mlinenum of- Just l -> putStrLn . unwords . map show $ fromMaybe [] (fst <$> IM.lookup l lineMap)- Nothing -> do- let lineBs = B.lines contents- let maxLen = maximum (0:map B.length lineBs)- forM_ (zip lineBs [1..]) $ \ (line, l) -> do- let nodeIDs = fromMaybe [] (fst <$> IM.lookup l lineMap)- let nodeStr = B.intercalate "," (map (B.pack . ('B':) . show) nodeIDs)- let suffix | null nodeIDs = ""- | otherwise = B.replicate (maxLen - B.length line + 1) ' ' <> "!" <> nodeStr- B.putStrLn $ line <> suffix- _ -> fail $ usageInfo programName options- _ -> fail $ usageInfo programName options----- | Expand all paths that are directories into a list of Fortran--- files from a recursive directory listing.-expandDirs :: [FilePath] -> IO [FilePath]-expandDirs = fmap concat . mapM each- where- each path = do- isDir <- doesDirectoryExist path- if isDir- then listFortranFiles path- else pure [path]---- | Get a list of Fortran files under the given directory.-listFortranFiles :: FilePath -> IO [FilePath]-listFortranFiles dir = filter isFortran <$> listDirectoryRecursively dir- where- -- | True if the file has a valid fortran extension.- isFortran :: FilePath -> Bool- isFortran x = map toLower (takeExtension x) `elem` exts- where exts = [".f", ".f90", ".f77", ".f03"]--listDirectoryRecursively :: FilePath -> IO [FilePath]-listDirectoryRecursively dir = listDirectoryRec dir ""- where- listDirectoryRec :: FilePath -> FilePath -> IO [FilePath]- listDirectoryRec d f = do- let fullPath = d </> f- isDir <- doesDirectoryExist fullPath- if isDir- then do- conts <- listDirectory fullPath- concat <$> mapM (listDirectoryRec fullPath) conts- else pure [fullPath]--compileFileToMod :: Maybe FortranVersion -> ModFiles -> FilePath -> Maybe FilePath -> IO ModFile-compileFileToMod mvers mods path moutfile = do- contents <- flexReadFile path- let version = fromMaybe (deduceFortranVersion path) mvers- let parserF0 = parserWithModFilesVersions version- let parserF m b s = fromRight (parserF0 m b s)- let mmap = combinedModuleMap mods- let tenv = combinedTypeEnv mods- let runCompile = genModFile . fst . analyseTypesWithEnv tenv . analyseRenamesWithModuleMap mmap . initAnalysis- let mod = runCompile $ parserF mods contents path- let fspath = path -<.> modFileSuffix `fromMaybe` moutfile- LB.writeFile fspath $ encodeModFile [mod]- return mod--decodeModFiles :: [String] -> IO ModFiles-decodeModFiles = flip foldM emptyModFiles $ \ modFiles d -> do- -- Figure out the camfort mod files and parse them.- modFileNames <- filter isModFile `fmap` getDirContents d- addedModFiles <- concat <$> mapM (decodeOneModFile . (d </>)) modFileNames- return $ addedModFiles ++ modFiles--decodeOneModFile :: FilePath -> IO ModFiles-decodeOneModFile path = do- contents <- LB.readFile path- case decodeModFile contents of- Left msg -> do- hPutStrLn stderr $ path ++ ": Error: " ++ msg- return []- Right modFiles -> do- hPutStrLn stderr $ path ++ ": successfully parsed summary file."- return modFiles--isModFile :: FilePath -> Bool-isModFile = (== modFileSuffix) . takeExtension--superGraphDataFlow :: forall a. (Out a, Data a) => ProgramFile (Analysis a) -> SuperBBGr (Analysis a) -> String-superGraphDataFlow pf sgr = showBBGr (bbgrMap (nmap (map (fmap insLabel))) gr') ++ "\n\n" ++ replicate 50 '-' ++ "\n\n" ++- show entries ++ "\n\n" ++ replicate 50 '-' ++ "\n\n" ++- dfStr gr'- where- gr' = superBBGrGraph sgr- entries = superBBGrEntries sgr- dfStr gr = (\ (l, x) -> '\n':l ++ ": " ++ x) =<< [- ("callMap", show cm)- , ("entries", show (bbgrEntries gr))- , ("exits", show (bbgrExits gr))- , ("postOrder", show (postOrder gr))- , ("revPostOrder", show (revPostOrder gr))- , ("revPreOrder", show (revPreOrder gr))- , ("dominators", show (dominators gr))- , ("iDominators", show (iDominators gr))- , ("defMap", show dm)- , ("lva", show (IM.toList $ lva gr))- , ("rd", show (IM.toList rDefs))- , ("backEdges", show bedges)- , ("topsort", show (topsort $ bbgrGr gr))- , ("scc ", show (scc $ bbgrGr gr))- , ("loopNodes", show (loopNodes bedges $ bbgrGr gr))- , ("duMap", show (genDUMap bm dm gr rDefs))- , ("udMap", show (genUDMap bm dm gr rDefs))- , ("flowsTo", show (edges flTo))- , ("varFlowsTo", show (genVarFlowsToMap dm flTo))- , ("ivMap", show (genInductionVarMap bedges gr))- , ("blockMap", unlines [ "AST-block " ++ show i ++ ":\n" ++ pretty b | (i, b) <- IM.toList bm ])- , ("derivedInd", unlines [ "Expression " ++ show i ++ " (IE: " ++ show ie ++ "):\n" ++ pretty e- | e <- universeBi bm :: [Expression (Analysis a)]- , i <- maybeToList (insLabel (getAnnotation e))- , let ie = IM.lookup i diMap ])- , ("constExpMap", show (genConstExpMap pf))- ] where- bedges = genBackEdgeMap (dominators gr) $ bbgrGr gr- flTo = genFlowsToGraph bm dm gr rDefs- rDefs = rd gr- diMap = genDerivedInductionMap bedges gr- lva = liveVariableAnalysis- bm = genBlockMap pf- dm = genDefMap bm- rd = reachingDefinitions dm- cm = genCallMap pf--showGenericMap :: (Show a, Show b) => M.Map a b -> String-showGenericMap = unlines . map (\ (k, v) -> show k ++ " : " ++ show v) . M.toList-showStringMap :: StringMap -> String-showStringMap = showGenericMap-showModuleMap :: ModuleMap -> String-showModuleMap = concatMap (\ (n, m) -> show n ++ ":\n" ++ (unlines . map (" "++) . lines . showGenericMap $ m)) . M.toList-showTypes :: TypeEnv -> String-showTypes tenv =- flip concatMap (M.toList tenv) $- \ (name, IDType { idVType = vt, idCType = ct }) ->- printf "%s\t\t%s %s\n" name (drop 1 $ maybe " -" show vt) (drop 2 $ maybe " " show ct)-printTypes :: TypeEnv -> IO ()-printTypes = putStrLn . showTypes-showTypeErrors :: [TypeError] -> String-showTypeErrors errs = unlines [ show ss ++ ": " ++ msg | (msg, ss) <- sortBy (comparing snd) errs ]-printTypeErrors :: [TypeError] -> IO ()-printTypeErrors = putStrLn . showTypeErrors--data Action- = Lex | Parse | Typecheck | Rename | BBlocks | SuperGraph | Reprint | DumpModFile | Compile- | ShowFlows Bool Bool Int | ShowBlocks (Maybe Int) | ShowMakeGraph | Make- deriving Eq--instance Read Action where- readsPrec _ value =- let options' = [ ("lex", Lex) , ("parse", Parse) ] in- tryTypes options'- where- tryTypes [] = []- tryTypes ((attempt,result):xs) =- if map toLower value == attempt then [(result, "")] else tryTypes xs--data OutputFormat = Default | DOT deriving Eq--data Options = Options- { fortranVersion :: Maybe FortranVersion- , action :: Action- , outputFormat :: OutputFormat- , outputFile :: Maybe FilePath- , includeDirs :: [String]- , useContinuationReformatter :: Bool- }--initOptions :: Options-initOptions = Options Nothing Parse Default Nothing [] False--options :: [OptDescr (Options -> Options)]-options =- [ Option ['v','F']- ["fortranVersion"]- (ReqArg (\v opts -> opts { fortranVersion = selectFortranVersion v }) "VERSION")- "Fortran version to use, format: Fortran[66/77/77Legacy/77Extended/90]"- , Option ['a']- ["action"]- (ReqArg (\a opts -> opts { action = read a }) "ACTION")- "lex or parse action"- , Option ['t']- ["typecheck"]- (NoArg $ \ opts -> opts { action = Typecheck })- "parse and run typechecker"- , Option ['R']- ["rename"]- (NoArg $ \ opts -> opts { action = Rename })- "parse and rename variables"- , Option ['B']- ["bblocks"]- (NoArg $ \ opts -> opts { action = BBlocks })- "analyse basic blocks"- , Option ['S']- ["supergraph"]- (NoArg $ \ opts -> opts { action = SuperGraph })- "analyse super graph of basic blocks"- , Option ['r']- ["reprint"]- (NoArg $ \ opts -> opts { action = Reprint })- "Parse and output using pretty printer"- , Option []- ["split-long"]- (NoArg $ \ opts -> opts { useContinuationReformatter = True })- "when using pretty printer, split long lines via continuations"- , Option []- ["dot"]- (NoArg $ \ opts -> opts { outputFormat = DOT })- "output graphs in GraphViz DOT format"- , Option []- ["dump-mod-file"]- (NoArg $ \ opts -> opts { action = DumpModFile })- "dump the information contained within mod files"- , Option ['I']- ["include-dir"]- (ReqArg (\ d opts -> opts { includeDirs = d:includeDirs opts }) "DIR")- "directory to search for precompiled 'mod files'"- , Option ['c']- ["summarise", "compile-mod"]- (NoArg $ \ opts -> opts { action = Compile })- "build an .fsmod file from the input"- , Option ['o']- ["output-file"]- (ReqArg (\ f opts -> opts { outputFile = Just f }) "FILE")- "name of output file (e.g. name of generated fsmod file)"- , Option []- ["make-mods", "make"]- (NoArg $ \ opts -> opts { action = Make })- "determine dependency order of modules and automatically build .fsmod files"- , Option []- ["show-make-graph"]- (NoArg $ \ opts -> opts { action = ShowMakeGraph })- "dump a graph showing the build structure of modules"- , Option []- ["show-block-numbers"]- (OptArg (\a opts -> opts { action = ShowBlocks (a >>= readMaybe) }- ) "LINE-NUM")- "Show the corresponding AST-block identifier number next to every line of code."- , Option []- ["show-flows-to"]- (ReqArg (\a opts -> case a of s:num | toLower s == 's' -> opts { action = ShowFlows False True (read num) }- b:num | toLower b == 'b' -> opts { action = ShowFlows False False (read num) }- num -> opts { action = ShowFlows False False (read num) }- ) "AST-BLOCK-ID")- "dump a graph showing flows-to information from the given AST-block ID; prefix with 's' for supergraph"- , Option []- ["show-flows-from"]- (ReqArg (\a opts -> case a of s:num | toLower s == 's' -> opts { action = ShowFlows True True (read num) }- b:num | toLower b == 'b' -> opts { action = ShowFlows True False (read num) }- num -> opts { action = ShowFlows True False (read num) }- ) "AST-BLOCK-ID")- "dump a graph showing flows-from information from the given AST-block ID; prefix with 's' for supergraph"- ]--compileArgs :: [ String ] -> IO (Options, [ String ])-compileArgs args =- case getOpt Permute options args of- (o, n, []) -> return (foldl (flip id) initOptions o, n)- (_, _, errors) -> ioError $ userError $ concat errors ++ usageInfo header options- where- header = "Usage: " ++ programName ++ " [OPTION...] <file...>"--instance {-# OVERLAPPING #-} Show [ FixedForm.Token ] where- show = unlines . lines'- where- lines' [] = []- lines' xs =- let (x, xs') = break isNewline xs- in case xs' of- (nl@(FixedForm.TNewline _):xs'') -> ('\t' : (intercalate ", " . map show $ x ++ [nl])) : lines' xs''- xs'' -> [ show xs'' ]- isNewline (FixedForm.TNewline _) = True- isNewline _ = False--instance {-# OVERLAPPING #-} Show [ FreeForm.Token ] where- show = unlines . lines'- where- lines' [] = []- lines' xs =- let (x, xs') = break isNewline xs- in case xs' of- (nl@(FreeForm.TNewline _):xs'') -> ('\t' : (intercalate ", " . map show $ x ++ [nl])) : lines' xs''- xs'' -> [ show xs'' ]- isNewline (FreeForm.TNewline _) = True- isNewline _ = False
test/Language/Fortran/Analysis/BBlocksSpec.hs view
@@ -2,8 +2,7 @@ import Test.Hspec -import Language.Fortran.Parser.Fortran77-import Language.Fortran.ParserMonad (fromParseResultUnsafe)+import qualified Language.Fortran.Parser as Parser import Language.Fortran.AST import Language.Fortran.Analysis import Language.Fortran.Analysis.BBlocks@@ -15,8 +14,10 @@ import qualified Data.ByteString.Char8 as B pParser :: String -> ProgramFile (Analysis ())-pParser source = rename . analyseBBlocks . analyseRenames . initAnalysis . fromParseResultUnsafe- $ extended77Parser (B.pack source) "<unknown>"+pParser source =+ case Parser.f77e "<unknown>" (B.pack source) of+ Left err -> error $ show err+ Right pf -> rename . analyseBBlocks . analyseRenames . initAnalysis $ pf spec :: Spec spec =
test/Language/Fortran/Analysis/DataFlowSpec.hs view
@@ -6,14 +6,13 @@ import Test.Hspec.QuickCheck import Test.QuickCheck (Positive(..)) -import Language.Fortran.Parser.Fortran77-import qualified Language.Fortran.Parser.Fortran90 as F90-import Language.Fortran.ParserMonad (fromParseResultUnsafe) import Language.Fortran.AST import Language.Fortran.Analysis import Language.Fortran.Analysis.Renaming import Language.Fortran.Analysis.BBlocks import Language.Fortran.Analysis.DataFlow+import qualified Language.Fortran.Parser as Parser+ import qualified Data.Map as M import qualified Data.Set as S import qualified Data.IntMap as IM@@ -26,24 +25,22 @@ import qualified Data.ByteString.Char8 as B import Control.Arrow ((&&&)) -{-# ANN module "HLint: ignore Reduce duplication" #-}- data F77 = F77 data F90 = F90 class Parser t where- parser :: t -> String -> String -> ProgramFile A0+ parser :: t -> String -> ProgramFile A0 instance Parser F77 where- parser F77 src file = fromParseResultUnsafe $ extended77Parser (B.pack src) file+ parser F77 = Parser.parseUnsafe Parser.f77e . B.pack instance Parser F90 where- parser F90 src file = fromParseResultUnsafe $ F90.fortran90Parser (B.pack src) file+ parser F90 = Parser.parseUnsafe Parser.f90 . B.pack pParser :: Parser t => t -> String -> ProgramFile (Analysis ()) pParser version source = rename . analyseBBlocks . analyseRenames . initAnalysis- . resetSrcSpan $ parser version source "<unknown>"+ . resetSrcSpan $ parser version source withParse :: Data a => Parser t => t -> String -> (ProgramFile (Analysis A0) -> a) -> a-withParse version source f = underRenaming (f . analyseBBlocks) (parser version source "<unknown>")+withParse version source f = underRenaming (f . analyseBBlocks) (parser version source) testGraph :: Parser t => t -> String -> String -> BBGr (Analysis A0) testGraph version f p = fromJust . M.lookup (Named f) . withParse version p $ genBBlockMap
test/Language/Fortran/Analysis/RenamingSpec.hs view
@@ -7,11 +7,10 @@ --import Data.Data (Data) import qualified Data.Map as M -import Language.Fortran.ParserMonad import Language.Fortran.AST-import qualified Language.Fortran.Parser.Fortran90 as F90 import Language.Fortran.Analysis import Language.Fortran.Analysis.Renaming+import qualified Language.Fortran.Parser as Parser import Data.Generics.Uniplate.Data import qualified Data.ByteString.Char8 as B @@ -34,8 +33,8 @@ where uniE_PF :: ProgramFile (Analysis ()) -> [Expression (Analysis ())] uniE_PF = universeBi -fortran90Parser :: String -> String -> ProgramFile A0-fortran90Parser src file = fromParseResultUnsafe $ F90.fortran90Parser (B.pack src) file+fortran90Parser :: String -> ProgramFile A0+fortran90Parser = Parser.parseUnsafe Parser.f90 . B.pack spec :: Spec spec = do@@ -112,7 +111,7 @@ -- GitHub issue #190 https://github.com/camfort/fortran-src/issues/190 it "doesn't generate same unique name in edge case" $ do- let ex = resetSrcSpan . flip fortran90Parser "" $ unlines+ let ex = resetSrcSpan . fortran90Parser $ unlines [ "program p1" , " implicit none" , " integer x, int1, a1, a2, a3, a4, a5, a6, a7, a8, a9"@@ -208,7 +207,7 @@ , BlStatement () u Nothing (StExpressionAssign () u (ExpValue () u (ValVariable "r")) (ExpFunctionCall () u (ExpValue () u (ValVariable "f1"))- (Just $ AList () u [ Argument () u Nothing $ intGen 1 ]))) ]+ (Just $ AList () u [ Argument () u Nothing $ aintGen 1 ]))) ] ex4pu2 :: ProgramUnit () ex4pu2 = PUFunction () u (Just $ TypeSpec () u TypeInteger Nothing) emptyPrefixSuffix "f1" (Just $ AList () u [ varGen "x"]) Nothing [ BlStatement () u Nothing (StExpressionAssign () u (varGen "f1") (varGen "x")) ] Nothing @@ -236,13 +235,13 @@ ex6pu2bs :: [a] ex6pu2bs = [] ex6pu2pu1 :: ProgramUnit ()-ex6pu2pu1 = PUFunction () u (Just $ TypeSpec () u TypeInteger Nothing) emptyPrefixSuffix "f1" (Just $ AList () u [ varGen "x"]) Nothing [ BlStatement () u Nothing (StExpressionAssign () u (varGen "f1") (ExpFunctionCall () u (ExpValue () u (ValVariable "f1")) (Just $ AList () u [Argument () u Nothing (varGen "x")]))) ] (Just [ex5pu2pu1])+ex6pu2pu1 = PUFunction () u (Just $ TypeSpec () u TypeInteger Nothing) emptyPrefixSuffix "f1" (Just $ AList () u [ varGen "x"]) Nothing [ BlStatement () u Nothing (StExpressionAssign () u (varGen "f1") (ExpFunctionCall () u (ExpValue () u (ValVariable "f1")) (Just $ AList () u [Argument () u Nothing (ArgExpr $ varGen "x")]))) ] (Just [ex5pu2pu1]) --parseF90 :: [String] -> ProgramFile A0---parseF90 = resetSrcSpan . flip fortran90Parser "" . unlines+--parseF90 = resetSrcSpan . fortran90Parser . unlines ex8 :: ProgramFile A0-ex8 = resetSrcSpan . flip fortran90Parser "" $ unlines [+ex8 = resetSrcSpan . fortran90Parser $ unlines [ "module m1" , " implicit none" , "contains"@@ -277,7 +276,7 @@ ] ex9 :: ProgramFile A0-ex9 = resetSrcSpan . flip fortran90Parser "" $ unlines [+ex9 = resetSrcSpan . fortran90Parser $ unlines [ "module m1" , " implicit none" , " integer :: x"@@ -313,7 +312,7 @@ , BlStatement () u Nothing (StEntry () u (ExpValue () u (ValVariable "e3")) Nothing (Just (varGen "r2"))) ] ex12 :: ProgramFile A0-ex12 = resetSrcSpan . flip fortran90Parser "" $ unlines [+ex12 = resetSrcSpan . fortran90Parser $ unlines [ "module m1" , " implicit none" , " integer :: z"@@ -350,7 +349,7 @@ ] ex13Renames :: ProgramFile A0-ex13Renames = resetSrcSpan . flip fortran90Parser "" $ unlines [+ex13Renames = resetSrcSpan . fortran90Parser $ unlines [ "module m1" , " implicit none" , " integer :: z"@@ -388,7 +387,7 @@ exScope1 :: ProgramFile A0-exScope1 = resetSrcSpan . flip fortran90Parser "" $ unlines [+exScope1 = resetSrcSpan . fortran90Parser $ unlines [ "program scope1" -- local variables cannot take on the name of subprogram, therefore -- this declaration must be simply redeclaring the function x.@@ -404,7 +403,7 @@ ] exScope2 :: ProgramFile A0-exScope2 = resetSrcSpan . flip fortran90Parser "" $ unlines [+exScope2 = resetSrcSpan . fortran90Parser $ unlines [ "module scope2" , " integer :: x" , "contains"@@ -434,7 +433,7 @@ ] exScope3 :: ProgramFile A0-exScope3 = resetSrcSpan . flip fortran90Parser "" $ unlines [+exScope3 = resetSrcSpan . fortran90Parser $ unlines [ "module m1" , " implicit none" , " integer :: x"@@ -471,7 +470,7 @@ ] common1 :: ProgramFile A0-common1 = resetSrcSpan . flip fortran90Parser "" $ unlines [+common1 = resetSrcSpan . fortran90Parser $ unlines [ "program p1" , " implicit none" , " integer :: x, y"
test/Language/Fortran/Analysis/TypesSpec.hs view
@@ -12,9 +12,7 @@ import Language.Fortran.Analysis.Types import Language.Fortran.Analysis.SemanticTypes import Language.Fortran.Analysis.Renaming-import qualified Language.Fortran.Parser.Fortran77 as F77-import qualified Language.Fortran.Parser.Fortran90 as F90-import Language.Fortran.ParserMonad+import qualified Language.Fortran.Parser as Parser import qualified Data.ByteString.Char8 as B inferTable :: Data a => ProgramFile a -> TypeEnv@@ -23,11 +21,11 @@ typedProgramFile :: Data a => ProgramFile a -> ProgramFile (Analysis a) typedProgramFile = fst . analyseTypes . analyseRenames . initAnalysis -legacy77Parser :: String -> String -> ProgramFile A0-legacy77Parser src file = fromParseResultUnsafe $ F77.legacy77Parser (B.pack src) file+legacy77Parser :: String -> ProgramFile A0+legacy77Parser = Parser.parseUnsafe Parser.f77l . B.pack -fortran90Parser :: String -> String -> ProgramFile A0-fortran90Parser src file = fromParseResultUnsafe $ F90.fortran90Parser (B.pack src) file+fortran90Parser :: String -> ProgramFile A0+fortran90Parser = Parser.parseUnsafe Parser.f90 . B.pack uniExpr :: ProgramFile (Analysis A0) -> [Expression (Analysis A0)] uniExpr = universeBi@@ -386,11 +384,11 @@ -- | Parse a string as an F90 program with initialized 'SrcSpan's. parseStrF90 :: String -> ProgramFile A0-parseStrF90 = resetSrcSpan . flip fortran90Parser ""+parseStrF90 = resetSrcSpan . fortran90Parser commonTransform :: [String] -> String -> [String] -> Bool -> ProgramFile A0 commonTransform front cdecl back common =- resetSrcSpan . flip legacy77Parser "" . unlines . (++) front $+ resetSrcSpan . legacy77Parser . unlines . (++) front $ if common then cdecl : back else back structArray :: Bool -> ProgramFile A0
test/Language/Fortran/AnalysisSpec.hs view
@@ -3,16 +3,14 @@ import Test.Hspec import TestUtil -import Language.Fortran.Parser.Fortran77-import Language.Fortran.ParserMonad (fromParseResultUnsafe)-import Language.Fortran.AST import Language.Fortran.Analysis+import Language.Fortran.AST+import qualified Language.Fortran.Parser as Parser+ import qualified Data.ByteString.Char8 as B -pParser :: String -> ProgramFile (Analysis ())-pParser source = initAnalysis- . fromParseResultUnsafe- $ extended77Parser (B.pack source) "<unknown>"+pParser :: String -> ProgramFile (Analysis A0)+pParser = initAnalysis . Parser.parseUnsafe Parser.f77e . B.pack spec :: Spec spec =
− test/Language/Fortran/Lexer/FixedFormSpec.hs
@@ -1,312 +0,0 @@-module Language.Fortran.Lexer.FixedFormSpec where--import Language.Fortran.ParserMonad---import Language.Fortran.Version (required when ParserMonad stops exporting it)-import Language.Fortran.Lexer.FixedForm-import Language.Fortran.AST.Boz--import Test.Hspec-import Test.Hspec.QuickCheck-import TestUtil--import Data.List (isPrefixOf)-import qualified Data.ByteString.Char8 as B--lex66 :: String -> Maybe Token-lex66 = collectToLex Fortran66--safeLex66 :: String -> Maybe Token-safeLex66 = collectToLexSafe Fortran66--lex77 :: String -> Maybe Token-lex77 = collectToLex Fortran77--collectToLex :: FortranVersion -> String -> Maybe Token-collectToLex version srcInput = dropUntil2 $ collectFixedTokens version (B.pack srcInput)- where- dropUntil2 [] = Nothing- dropUntil2 [_] = Nothing- dropUntil2 [a,_] = Just a- dropUntil2 (_:xs) = dropUntil2 xs--collectToLexSafe :: FortranVersion -> String -> Maybe Token-collectToLexSafe version srcInput = dropUntil2 $ collectFixedTokensSafe version (B.pack srcInput)- where- dropUntil2 (Just [a,_]) = Just a- dropUntil2 (Just (_:xs)) = dropUntil2 $ Just xs- dropUntil2 _ = Nothing--collectFixedTokens' :: FortranVersion -> String -> [Token]-collectFixedTokens' v = collectFixedTokens v . B.pack--spec :: Spec-spec =- describe "Fortran Fixed Form Lexer" $ do- describe "Fortran 77" $- describe "String" $ do- it "lexes 'hello'" $- resetSrcSpan (lex77 " c = 'hello'") `shouldBe` resetSrcSpan (Just $ TString u "hello")-- it "lexes 'he''llo'" $- resetSrcSpan (lex77 " c = 'he''llo'") `shouldBe` resetSrcSpan (Just $ TString u "he'llo")-- it "lexes 'he''''ll''o'" $- resetSrcSpan (lex77 " c = 'he''''ll''o'") `shouldBe` resetSrcSpan (Just $ TString u "he''ll'o")-- it "lexes '''hello'''" $- resetSrcSpan (lex77 " c = '''hello'''") `shouldBe` resetSrcSpan (Just $ TString u "'hello'")-- it "lexes 'hello world'" $- resetSrcSpan (lex77 " c = 'hello world'") `shouldBe` resetSrcSpan (Just $ TString u "hello world")-- it "lexes 'hello world'" $- resetSrcSpan (collectFixedTokens' Fortran77 " c = 'x' // 'o'") `shouldBe` resetSrcSpan [TId u "c", TOpAssign u, TString u "x", TSlash u, TSlash u, TString u "o", TEOF u]-- describe "Fortran 66" $ do- prop "lexes Label, Comment, Newline or EOF in the first six columns or returns Nothing " $- \x -> isPrefixOf " " x || case safeLex66 x of- Nothing -> True- Just (TLabel _ _) -> True- Just (TComment _ _) -> True- Just (TEOF _) -> True- Just (TNewline _) -> True- _ -> False-- it "lexes alphanumeric identifier" $- resetSrcSpan (collectFixedTokens' Fortran66 " e42 =") `shouldBe` resetSrcSpan [TId u "e42", TOpAssign u, TEOF u]-- it "lexes exponent" $- resetSrcSpan (collectFixedTokens' Fortran66 " a = 42 e42") `shouldBe` resetSrcSpan [TId u "a", TOpAssign u, TInt u "42", TExponent u "e42", TEOF u]-- it "lexes 'function foo()'" $- resetSrcSpan (collectFixedTokens' Fortran66 " function foo()") `shouldBe` resetSrcSpan [TFunction u, TId u "foo", TLeftPar u, TRightPar u, TEOF u]-- it "lexes 'end'" $- resetSrcSpan (lex66 " end") `shouldBe` resetSrcSpan (Just $ TEnd u)-- it "lexes identifier" $- resetSrcSpan (lex66 " a = mistr") `shouldBe` resetSrcSpan (Just $ TId u "mistr")-- it "lexes comment if first column is C" $- resetSrcSpan (lex66 "c this is a comment") `shouldBe` resetSrcSpan (Just $ TComment u " this is a comment")-- it "lexes empty comment" $- resetSrcSpan (lex66 "c") `shouldBe` resetSrcSpan (Just $ TComment u "")-- it "lexes comment with one char" $- resetSrcSpan (lex66 "ca") `shouldBe` resetSrcSpan (Just $ TComment u "a")-- it "should not lex from the next line" $- resetSrcSpan (safeLex66 "cxxx\nselam") `shouldNotBe` resetSrcSpan (Just $ TComment u "xxxselam")-- -- This is commented out as identifiers are longer than what the standard says.- it "lexes three tokens" $ do- pending- resetSrcSpan (collectFixedTokens' Fortran66 " function end format") `shouldBe` resetSrcSpan [TFunction u, TId u "endfor", TId u "mat", TEOF u]-- it "lexes multiple comments in a line" $- resetSrcSpan (collectFixedTokens' Fortran66 "csomething\ncsomething else\n\nc\ncc\n") `shouldBe`- resetSrcSpan [TComment u "something", TNewline u, TComment u "something else", TNewline u, TNewline u, TComment u "", TNewline u, TComment u "c", TNewline u, TEOF u]-- it "lexes example1" $- resetSrcSpan (collectFixedTokens' Fortran66 example1) `shouldBe` resetSrcSpan example1Expectation-- it "lexes end of file" $- resetSrcSpan (lex66 "") `shouldBe` Nothing-- it "lexes '3 + 2'" $- resetSrcSpan (collectFixedTokens' Fortran66 " a = 3 + 2") `shouldBe` resetSrcSpan [TId u "a", TOpAssign u, TInt u "3", TOpPlus u , TInt u "2", TEOF u]-- it "should lex continuation lines properly" $- resetSrcSpan (collectFixedTokens' Fortran66 continuationExample) `shouldBe` resetSrcSpan [ TType u "integer", TId u "ix", TNewline u, TId u "ix", TOpAssign u, TInt u "42", TNewline u, TEnd u, TNewline u, TEOF u ]-- it "lexes 'ASSIGN 100 TO FOO'" $- resetSrcSpan (collectFixedTokens' Fortran66 " ASSIGN 100 TO FOO") `shouldBe` resetSrcSpan [TAssign u, TInt u "100", TTo u, TId u "foo", TEOF u]-- it "lexes 'DO 100 dovar = 1, 10'" $- resetSrcSpan (collectFixedTokens' Fortran66 " DO 100 dovar = 1, 10")- `shouldBe`- resetSrcSpan [TDo u, TInt u "100", TId u "dovar", TOpAssign u, TInt u "1", TComma u, TInt u "10", TEOF u]-- describe "lexN" $- it "`lexN 5` parses lexes next five characters" $- (lexemeMatch . aiLexeme) (evalParse (lexN 5 >> getAlex) (initParseState (B.pack "helloWorld") Fortran66 "")) `shouldBe` reverse "hello"-- describe "lexHollerith" $ do- it "lexes Hollerith '7hmistral'" $- resetSrcSpan (lex66 " x = 7hmistral") `shouldBe` resetSrcSpan (Just $ THollerith u "mistral")-- it "becomes case sensitive" $- resetSrcSpan (collectFixedTokens' Fortran66 " format (5h a= 1)") `shouldBe` resetSrcSpan [ TFormat u, TBlob u "(5ha=1)", TEOF u ]-- it "lexes if statement ' IF (IY) 5,6,6'" $- resetSrcSpan (collectFixedTokens' Fortran66 " IF (IY) 5,6,6") `shouldBe` resetSrcSpan [TIf u, TLeftPar u, TId u "iy", TRightPar u, TInt u "5", TComma u, TInt u "6", TComma u, TInt u "6", TEOF u]-- it "lexes if then statement ' if (x) then'" $- resetSrcSpan (collectFixedTokens' Fortran77 " if (x) then") `shouldBe` resetSrcSpan [TIf u, TLeftPar u, TId u "x", TRightPar u, TThen u, TEOF u]-- it "lexes if variable decl ' INTEGER IF'" $ -- yes, really..- resetSrcSpan (collectFixedTokens' Fortran77 " INTEGER IF")- `shouldBe` resetSrcSpan [TType u "integer", TId u "if", TEOF u]-- describe "Fortran 77 Legacy" $ do- it "lexes inline comments" $- resetSrcSpan (collectFixedTokens' Fortran77Legacy " integer foo ! bar")- `shouldBe` resetSrcSpan [TType u "integer", TId u "foo", TEOF u]-- it "lexes continuation lines separated by comments" $ do- let src = unlines [ " integer foo,"- , "C hello"- , " + bar"- ]- in resetSrcSpan (collectFixedTokens' Fortran77Legacy src)- `shouldBe` resetSrcSpan [TType u "integer", TId u "foo", TComma u, TId u "bar", TNewline u, TEOF u]- let src = unlines [ " integer foo, ! hello"- , " + bar"- ]- in resetSrcSpan (collectFixedTokens' Fortran77Legacy src)- `shouldBe` resetSrcSpan [TType u "integer", TId u "foo", TComma u, TId u "bar", TNewline u, TEOF u]- let src = unlines [ " integer foo,"- , ""- , " + bar"- ]- in resetSrcSpan (collectFixedTokens' Fortran77Legacy src)- `shouldBe` resetSrcSpan [TType u "integer", TId u "foo", TComma u, TId u "bar", TNewline u, TEOF u]- let src = unlines [ " integer foo,"- , " " -- the space is intentional- , " + bar"- ]- in resetSrcSpan (collectFixedTokens' Fortran77Legacy src)- `shouldBe` resetSrcSpan [TType u "integer", TId u "foo", TComma u, TId u "bar", TNewline u, TEOF u]-- it "lexes the older TYPE statement" $- resetSrcSpan (collectFixedTokens' Fortran77Legacy " type *, 'hello'")- `shouldBe` resetSrcSpan [TTypePrint u, TStar u, TComma u, TString u "hello", TEOF u]-- it "lexes width-specific type declarations" $ do- resetSrcSpan (collectFixedTokens' Fortran77Legacy " integer*4 i")- `shouldBe` resetSrcSpan [TType u "integer", TStar u, TInt u "4", TId u "i", TEOF u]-- resetSrcSpan (collectFixedTokens' Fortran77Legacy " integer*4 function foo()")- `shouldBe` resetSrcSpan [TType u "integer", TStar u, TInt u "4", TFunction u, TId u "foo", TLeftPar u, TRightPar u, TEOF u]-- resetSrcSpan (collectFixedTokens' Fortran77Legacy " character*4 s")- `shouldBe` resetSrcSpan [TType u "character", TStar u, TInt u "4", TId u "s", TEOF u]-- resetSrcSpan (collectFixedTokens' Fortran77Legacy " character*(*) s")- `shouldBe` resetSrcSpan [TType u "character", TStar u, TLeftPar u, TStar u, TRightPar u, TId u "s", TEOF u]-- resetSrcSpan (collectFixedTokens' Fortran77Legacy " character s*(*)")- `shouldBe` resetSrcSpan [TType u "character", TId u "s", TStar u, TLeftPar u, TStar u, TRightPar u, TEOF u]-- it "lexes strings case-sensitively" $- resetSrcSpan (collectFixedTokens' Fortran77Legacy " c = 'Hello'")- `shouldBe` resetSrcSpan [TId u "c", TOpAssign u, TString u "Hello", TEOF u]-- it "lexes strings delimited by '\"'" $- resetSrcSpan (collectFixedTokens' Fortran77Legacy " c = \"hello\"")- `shouldBe` resetSrcSpan [TId u "c", TOpAssign u, TString u "hello", TEOF u]-- it "lexes Hollerith constants" $ do- resetSrcSpan (collectFixedTokens' Fortran77Legacy " x = 7hmistral")- `shouldBe` resetSrcSpan [TId u "x", TOpAssign u, THollerith u "mistral", TEOF u]-- resetSrcSpan (collectFixedTokens' Fortran77Legacy " x = 7hshort\n")- `shouldBe` resetSrcSpan [TId u "x", TOpAssign u, THollerith u "short ", TNewline u, TEOF u]-- it "lexes BOZ constants" $- resetSrcSpan (collectFixedTokens' Fortran77Legacy " integer i, j, k / b'0101', o'0755', z'ab01' /")- `shouldBe` resetSrcSpan [ TType u "integer"- , TId u "i", TComma u, TId u "j", TComma u, TId u "k"- , TSlash u, TBozLiteral u (parseBoz "b'0101'")- , TComma u, TBozLiteral u (parseBoz "o'0755'")- , TComma u, TBozLiteral u (parseBoz "z'ab01'")- , TSlash u , TEOF u ]-- it "lexes non-standard identifiers" $- resetSrcSpan (collectFixedTokens' Fortran77Legacy " integer _this_is_a_long_identifier$")- `shouldBe` resetSrcSpan [TType u "integer", TId u "_this_is_a_long_identifier$", TEOF u]-- it "lexes ';' as a line-terminator" $- 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]-- it "lexes labeled DO WHILE blocks" $- resetSrcSpan (collectFixedTokens' Fortran77Legacy " do 10 while (.true.)")- `shouldBe` resetSrcSpan [TDo u, TInt u "10", TWhile u, TLeftPar u, TBool u True, TRightPar u, TEOF u]-- it "lexes structure/union/map blocks" $ do- let src = unlines [ " structure /foo/"- , " union"- , " map"- , " integer i"- , " real r"- , " end map"- , " end union"- , " end structure"]- resetSrcSpan (collectFixedTokens' Fortran77Legacy src)- `shouldBe` resetSrcSpan [ TStructure u, TSlash u, TId u "foo", TSlash u, TNewline u- , TUnion u, TNewline u- , TMap u, TNewline u- , TType u "integer", TId u "i", TNewline u- , TType u "real", TId u "r", TNewline u- , TEndMap u, TNewline u- , TEndUnion u, TNewline u- , TEndStructure u, TNewline u- , TEOF u ]-- it "lexes but skips comments after 72" $ do- let src = unlines [ " l = r" <> replicate 65 ' ' <> "! comment after 72"- , " r = l"- , replicate 72 ' ' <> "blank line with comment"]- resetSrcSpan (collectFixedTokens' Fortran77Legacy src) `shouldBe`- resetSrcSpan [ TId u "l", TOpAssign u, TId u "r", TNewline u- , TId u "r", TOpAssign u, TId u "l", TNewline u- , TNewline u, TEOF u]- it "lexes comment overflow" $ do- let src = unlines- [ " l = r" <> replicate 65 ' ' <> "Comment overflowing 72 limit"- , " r = l"- ]- resetSrcSpan (collectFixedTokens' Fortran77Legacy src) `shouldBe`- resetSrcSpan [ TId u "l", TOpAssign u, TId u "r", TNewline u- , TId u "r", TOpAssign u, TId u "l", TNewline u, TEOF u]- it "lexel comment line overflow" $ do- let src = unlines [ replicate 80 'c'- , " l = r" ]- resetSrcSpan (collectFixedTokens' Fortran77Legacy src) `shouldBe`- resetSrcSpan [ TComment u (replicate 71 'c'), TNewline u- , TId u "l", TOpAssign u, TId u "r", TNewline u, TEOF u]--example1 :: String-example1 = unlines [- " intEGerix",- "1 iX= 42",- " 200 ix =IX* ix",- " 10 wrITe (*,*), ix",- " EnD" ]--continuationExample :: String-continuationExample = unlines [- " inte",- " .ger i",- " .x",- " ix = 4",- " .2",- " end"]--example1Expectation :: [Token]-example1Expectation = [- TType u "integer", TId u "ix", TNewline u,- TLabel u "1", TId u "ix", TOpAssign u, TInt u "42", TNewline u,- TLabel u "200", TId u "ix", TOpAssign u, TId u "ix", TStar u, TId u "ix", TNewline u,- TLabel u "10", TWrite u, TLeftPar u, TStar u, TComma u, TStar u, TRightPar u, TComma u, TId u "ix", TNewline u,- TEnd u, TNewline u,- TEOF u]
− test/Language/Fortran/Lexer/FreeFormSpec.hs
@@ -1,377 +0,0 @@-module Language.Fortran.Lexer.FreeFormSpec where--import Test.Hspec-import TestUtil--import Language.Fortran.AST.RealLit-import Language.Fortran.Version-import Language.Fortran.Lexer.FreeForm (collectFreeTokens, Token(..))-import Language.Fortran.Util.Position (SrcSpan)-import qualified Data.ByteString.Char8 as B--collectF90 :: String -> [ Token ]-collectF90 = collectFreeTokens Fortran90 . B.pack--collectF03 :: String -> [ Token ]-collectF03 = collectFreeTokens Fortran2003 . B.pack---pseudoAssign :: (SrcSpan -> Token) -> [Token]-pseudoAssign token = fmap ($u) [ flip TId "i", TOpAssign, token, TEOF ]--spec :: Spec-spec =- describe "Fortran Free Form Lexer" $- describe "Fortran 90" $ do- describe "Character sensitivity" $ do- it "lexes lower case tokens" $- shouldBe' (collectF90 "integer id") $- fmap ($u) [ TInteger, flip TId "id", TEOF ]-- it "lexes mixed case tokens" $- shouldBe' (collectF90 "InTEgeR ID") $- fmap ($u) [ TInteger, flip TId "id", TEOF ]-- describe "Identifier" $ do- it "lexes long ID names" $- shouldBe' (collectF90 "program long_id_name") $- fmap ($u) [ TProgram, flip TId "long_id_name", TEOF ]-- it "treats 'if' as ID if used in assignment" $- shouldBe' (collectF90 "if = 20") $- fmap ($u) [ flip TId "if", TOpAssign- , flip TIntegerLiteral "20", TEOF ]-- it "'result' is an identifier in spec. context" $- shouldBe' (collectF90 "integer :: result") $- fmap ($u) [ TInteger, TDoubleColon , flip TId "result"- , TEOF ]-- describe "Types" $ do- it "lexes length and kind selectors" $- shouldBe' (collectF90 "integer (KIND=1, LEN=1) :: kind, len") $- fmap ($u) [ TInteger, TLeftPar, TKind, TOpAssign- , flip TIntegerLiteral "1", TComma, TLen- , TOpAssign, flip TIntegerLiteral "1", TRightPar- , TDoubleColon , flip TId "kind", TComma- , flip TId "len", TEOF ]--- it "lexes simple type tokens" $- shouldBe' (collectF90 "character x") $- fmap ($u) [ TCharacter, flip TId "x", TEOF ]-- it "lexes simple type tokens in function" $- shouldBe' (collectF90 "character function x") $- fmap ($u) [ TCharacter, TFunction, flip TId "x", TEOF ]-- it "lexes character type with F77 length syntax (1)" $- shouldBe' (collectF90 "character * (*) function x") $- fmap ($u) [ TCharacter, TStar, TLeftPar, TStar, TRightPar, TFunction, flip TId "x", TEOF ]-- it "lexes character type with F77 length syntax (2)" $- shouldBe' (collectF90 "character * 20 function x") $- fmap ($u) [ TCharacter, TStar, flip TIntegerLiteral "20", TFunction, flip TId "x", TEOF ]-- it "lexes derived type tokens in function" $- shouldBe' (collectF90 "type (x) function x") $- fmap ($u) [ TType, TLeftPar, flip TId "x", TRightPar- , TFunction, flip TId "x", TEOF ]-- it "lexes interleaved type recursive tokens" $- shouldBe' (collectF90 "integer (KIND=10*2) recursive function x") $- fmap ($u) [ TInteger, TLeftPar, TKind, TOpAssign- , flip TIntegerLiteral "10" , TStar- , flip TIntegerLiteral "2", TRightPar, TRecursive- , TFunction, flip TId "x", TEOF ]-- it "lexes interleaved type recursive tokens (reversed)" $- shouldBe' (collectF90 "recursive integer (KIND=10*2) function x") $- fmap ($u) [ TRecursive, TInteger, TLeftPar, TKind, TOpAssign- , flip TIntegerLiteral "10" , TStar- , flip TIntegerLiteral "2", TRightPar, TFunction- , flip TId "x", TEOF ]-- describe "Function" $ do- it "lexes 'function fx ( a, b, c )'" $- shouldBe' (collectF90 "function fx ( a, b )") $- fmap ($u) [ TFunction, flip TId "fx", TLeftPar, flip TId "a"- , TComma, flip TId "b", TRightPar, TEOF ]-- it "lexes functions with specific result" $- shouldBe' (collectF90 "function fx (array) result (c_sum)") $- fmap ($u) [ TFunction, flip TId "fx", TLeftPar- , flip TId "array", TRightPar, TResult, TLeftPar- , flip TId "c_sum", TRightPar, TEOF ]-- it "lexes recursive functions" $- shouldBe' (collectF90 "recursive function fx (array)") $- fmap ($u) [ TRecursive, TFunction, flip TId "fx", TLeftPar- , flip TId "array", TRightPar, TEOF ]-- it "lexes recursive functions with result specified" $- shouldBe' (collectF90 "RECURSIVE FUNCTION FX (ARRAY) RESULT (C_SUM)") $- fmap ($u) [ TRecursive, TFunction, flip TId "fx", TLeftPar- , flip TId "array", TRightPar, TResult, TLeftPar- , flip TId "c_sum", TRightPar, TEOF ]-- describe "Attribute" $ do- it "lexes PARAMETER attribute" $- shouldBe' (collectF90 "integer, parameter :: x") $- fmap ($u) [ TInteger, TComma, TParameter, TDoubleColon- , flip TId "x", TEOF ]-- it "lexes INTENT attribute" $- shouldBe' (collectF90 "integer, intent (inout) :: x") $- fmap ($u) [ TInteger, TComma, TIntent, TLeftPar, TInOut- , TRightPar, TDoubleColon , flip TId "x", TEOF ]-- it "lexes DIMENSION attribute" $- shouldBe' (collectF90 "double precision, dimension (3:10) :: x") $- fmap ($u) [ TDoublePrecision, TComma, TDimension, TLeftPar- , flip TIntegerLiteral "3", TColon- , flip TIntegerLiteral "10" , TRightPar- , TDoubleColon , flip TId "x", TEOF ]-- it "lexes variable declaration with multiple attributes" $- shouldBe' (collectF90 "double precision, save, dimension(2), allocatable :: y") $- fmap ($u) [ TDoublePrecision, TComma, TSave, TComma- , TDimension, TLeftPar, flip TIntegerLiteral "2"- , TRightPar, TComma, TAllocatable, TDoubleColon- , flip TId "y", TEOF ]-- it "try to trick lexer into parsing variables as attributes (1)" $- shouldBe' (collectF90 "integer save, dimension(10), target") $- fmap ($u) [ TInteger, flip TId "save", TComma- , flip TId "dimension", TLeftPar, flip TIntegerLiteral "10", TRightPar, TComma- , flip TId "target", TEOF ]-- it "try to trick lexer into parsing variables as attributes (2)" $- shouldBe' (collectF90 "type(foo) save, dimension(10), target") $- fmap ($u) [ TType, TLeftPar, flip TId "foo", TRightPar, flip TId "save", TComma- , flip TId "dimension", TLeftPar, flip TIntegerLiteral "10", TRightPar, TComma- , flip TId "target", TEOF ]-- it "try to trick lexer into parsing variables as attributes (3)" $- shouldBe' (collectF90 "allocate(type(foo) :: errmsg(stat, source), source=x)") $- fmap ($u) [ TAllocate, TLeftPar, TType, TLeftPar, flip TId "foo", TRightPar, TDoubleColon- , flip TId "errmsg", TLeftPar, flip TId "stat", TComma, flip TId "source", TRightPar- , TComma, TSource, TOpAssign, flip TId "x", TRightPar, TEOF ]-- describe "Character" $ do- it "lexes single quote literal" $- shouldBe' (collectF90 "character c = 'heL\"Lo ''daRLing'") $- fmap ($u) [ TCharacter, flip TId "c", TOpAssign- , flip TString "heL\"Lo 'daRLing", TEOF ]-- it "lexes double quote literal" $- shouldBe' (collectF90 "character c = \"heL'Lo \"\"daRLing\"") $- fmap ($u) [ TCharacter, flip TId "c", TOpAssign- , flip TString "heL'Lo \"daRLing", TEOF ]-- describe "Module" $ do- it "lexes module statement" $- shouldBe' (collectF90 "module Hello_mod") $- fmap ($u) [ TModule, flip TId "hello_mod", TEOF ]-- it "lexes use statement" $- shouldBe' (collectF90 "use Hello_mod, hello => hi") $- fmap ($u) [ TUse, flip TId "hello_mod", TComma- , flip TId "hello", TArrow, flip TId "hi", TEOF ]-- it "lexes use statement with only" $- shouldBe' (collectF90 "use Hello_mod, only: a, b => c") $- fmap ($u) [ TUse, flip TId "hello_mod", TComma, TOnly- , TColon, flip TId "a", TComma, flip TId "b"- , TArrow, flip TId "c", TEOF ]-- describe "Label" $- it "lexes simple label" $- shouldBe' (collectF90 "010 print *, 'hello'") $- fmap ($u) [ flip TIntegerLiteral "010", TPrint, TStar, TComma- , flip TString "hello", TEOF ]-- describe "Conditional" $ do- it "lexes logical if with array assignment" $- shouldBe' (collectF90 "if (.true.) a(1) = 42") $- fmap ($u) [ TIf, TLeftPar, flip TLogicalLiteral True- , TRightPar, flip TId "a", TLeftPar- , flip TIntegerLiteral "1", TRightPar, TOpAssign- , flip TIntegerLiteral "42", TEOF ]-- it "lexes block if statement" $- shouldBe' (collectF90 "if (a > b) then") $- fmap ($u) [ TIf, TLeftPar, flip TId "a", TOpGT, flip TId "b"- , TRightPar, TThen, TEOF ]-- it "lexes arithmetic if statement" $- shouldBe' (collectF90 "if (a) 10, 11, 12") $- fmap ($u) [ TIf, TLeftPar, flip TId "a", TRightPar- , flip TIntegerLiteral "10", TComma- , flip TIntegerLiteral "11", TComma- , flip TIntegerLiteral "12" , TEOF ]-- it "lexes logical if statement" $- shouldBe' (collectF90 "if (a > b) print *, 'hello'") $- fmap ($u) [ TIf, TLeftPar, flip TId "a", TOpGT, flip TId "b"- , TRightPar, TPrint, TStar, TComma- , flip TString "hello", TEOF ]-- describe "Lexes numeric values" $ do- it "lexes integer" $- shouldBe' (collectF90 "i = 42") $- pseudoAssign $ flip TIntegerLiteral "42"-- describe "Real" $ do- it "lexes real (1)" $ do- let litStr = "10.5e2"- expectedLit = RealLit "10.5" (Exponent ExpLetterE "2")- expected = pseudoAssign $ flip TRealLiteral expectedLit- collectF90 ("i = "<>litStr) `shouldBe'` expected-- it "lexes real (2)" $ do- let litStr = "10."- expectedLit = RealLit "10.0" (Exponent ExpLetterE "0")- expected = pseudoAssign $ flip TRealLiteral expectedLit- collectF90 ("i = "<>litStr) `shouldBe'` expected-- it "lexes real (3)" $ do- let litStr = ".42"- expectedLit = RealLit "0.42" (Exponent ExpLetterE "0")- expected = pseudoAssign $ flip TRealLiteral expectedLit- collectF90 ("i = "<>litStr) `shouldBe'` expected-- it "lexes real (4)" $ do- let litStr = "42d-3"- expectedLit = RealLit "42.0" (Exponent ExpLetterD "-3")- expected = pseudoAssign $ flip TRealLiteral expectedLit- collectF90 ("i = "<>litStr) `shouldBe'` expected-- it "resolves disambiguity when xxx. follows relational operator" $- shouldBe' (collectF90 "if (10.EQ. 20)") $- fmap ($u) [ TIf, TLeftPar, flip TIntegerLiteral "10"- , TOpEQ, flip TIntegerLiteral "20"- , TRightPar, TEOF ]-- describe "Continuation" $ do- it "Single continuation char without space" $- shouldBe' (collectF90 "i = &\n42") $- pseudoAssign $ flip TIntegerLiteral "42"-- it "Single continuation char with space" $- shouldBe' (collectF90 "i = & \n \t 42") $- pseudoAssign $ flip TIntegerLiteral "42"-- it "Double continuation (1)" $- shouldBe' (collectF90 "i = &\n & 42") $- pseudoAssign $ flip TIntegerLiteral "42"-- it "Double continuation (2)" $- shouldBe' (collectF90 "i = 4&\n &2") $- pseudoAssign $ flip TIntegerLiteral "42"-- it "Continuation with comment" $- shouldBe' (collectF90 "i = 4&\n ! hello\n &2") $- pseudoAssign $ flip TIntegerLiteral "42"-- it "Continuation with inline comment" $- shouldBe' (collectF90 "i = & ! hi \n 42") $- pseudoAssign $ flip TIntegerLiteral "42"-- describe "Comment" $ do- it "Full line comment" $- shouldBe' (collectF90 "! = & ! hi \n") $- ($u) <$> [ flip TComment " = & ! hi ", TNewline , TEOF ]-- it "Inline comment" $- shouldBe' (collectF90 "i = 10 ! = & ! hi \n") $- ($u) <$> [ flip TId "i", TOpAssign- , flip TIntegerLiteral "10"- , flip TComment " = & ! hi ", TNewline , TEOF ]- it "Empty comment" $- shouldBe' (collectF90 "!\n") $- ($u) <$> [ flip TComment "", TNewline , TEOF ]-- describe "Subscripting" $ do- it "Strings nested in arrays" $- shouldBe' (collectF90 "a(1)(2:3) = 'we'") $- ($u) <$> [ flip TId "a", TLeftPar, flip TIntegerLiteral "1", TRightPar- , TLeftPar, flip TIntegerLiteral "2", TColon, flip TIntegerLiteral "3", TRightPar- , TOpAssign, flip TString "we", TEOF ]-- describe "Fortran95" $ do- it "lexes value attribute" $ do- shouldBe' (collectF03 "value :: a, b") $- fmap ($u) [ TValue, TDoubleColon, flip TId "a", TComma, flip TId "b", TEOF ]- shouldBe' (collectF03 "integer, value :: a, b") $- fmap ($u) [ TInteger, TComma, TValue, TDoubleColon, flip TId "a", TComma, flip TId "b", TEOF ]-- it "lexes volatile attribute" $ do- shouldBe' (collectF03 "volatile :: a, b") $- fmap ($u) [ TVolatile, TDoubleColon, flip TId "a", TComma, flip TId "b", TEOF ]- shouldBe' (collectF03 "integer, volatile :: a, b") $- fmap ($u) [ TInteger, TComma, TVolatile, TDoubleColon, flip TId "a", TComma, flip TId "b", TEOF ]-- describe "Fortran2003" $ do- it "lexes procedures" $- shouldBe' (collectF03 "PROCEDURE(a), SAVE :: b => c()") $- ($u) <$> [ TProcedure, TLeftPar, flip TId "a", TRightPar- , TComma, TSave, TDoubleColon- , flip TId "b", TArrow, flip TId "c", TLeftPar, TRightPar, TEOF ]-- it "lexes procedures with bind" $- shouldBe' (collectF03 "PROCEDURE(a), BIND(C, NAME=\"d\") :: b => c()") $- ($u) <$> [ TProcedure, TLeftPar, flip TId "a", TRightPar- , TComma, TBind, TLeftPar, TC, TComma, TName, TOpAssign, flip TString "d", TRightPar, TDoubleColon- , flip TId "b", TArrow, flip TId "c", TLeftPar, TRightPar, TEOF ]-- it "lexes functions with bind" $- shouldBe' (collectF03 "FUNCTION f(a) RESULT(x) BIND(C, NAME=\"d\")") $- ($u) <$> [ TFunction, flip TId "f", TLeftPar, flip TId "a", TRightPar- , TResult, TLeftPar, flip TId "x", TRightPar- , TBind, TLeftPar, TC, TComma, TName, TOpAssign, flip TString "d", TRightPar, TEOF ]-- it "lexes subroutines with bind" $- shouldBe' (collectF03 "SUBROUTINE s(a) BIND(C, NAME=\"d\")") $- ($u) <$> [ TSubroutine, flip TId "s", TLeftPar, flip TId "a", TRightPar- , TBind, TLeftPar, TC, TComma, TName, TOpAssign, flip TString "d", TRightPar, TEOF ]-- it "lexes class decl (name)" $- shouldBe' (collectF03 "procedure (class(c))") $- fmap ($u) [ TProcedure, TLeftPar- , TClass, TLeftPar, flip TId "c", TRightPar, TRightPar, TEOF ]-- it "lexes class decl (*)" $- shouldBe' (collectF03 "procedure (class(*))") $- fmap ($u) [ TProcedure, TLeftPar- , TClass, TLeftPar, TStar, TRightPar, TRightPar, TEOF ]-- it "lexes import statements" $- shouldBe' (collectF03 "import :: a, b") $- fmap ($u) [ TImport, TDoubleColon, flip TId "a", TComma, flip TId "b", TEOF ]-- it "lexes asynchronous attribute" $ do- shouldBe' (collectF03 "asynchronous :: a, b") $- fmap ($u) [ TAsynchronous, TDoubleColon, flip TId "a", TComma, flip TId "b", TEOF ]- shouldBe' (collectF03 "integer, asynchronous :: a, b") $- fmap ($u) [ TInteger, TComma, TAsynchronous, TDoubleColon, flip TId "a", TComma, flip TId "b", TEOF ]-- it "lexes enums" $ do- shouldBe' (collectF03 "enum, bind(c)") $ fmap ($u) [ TEnum, TComma, TBind, TLeftPar, TC, TRightPar, TEOF ]- shouldBe' (collectF03 "enumerator :: a = 1, b") $- fmap ($u) [ TEnumerator, TDoubleColon, flip TId "a", TOpAssign, flip TIntegerLiteral "1"- , TComma, flip TId "b", TEOF ]- shouldBe' (collectF03 "end enum") $ fmap ($u) [ TEndEnum, TEOF ]-- it "lexes flush" $ do- shouldBe' (collectF03 "flush(unit=1)") $- fmap ($u) [ TFlush, TLeftPar, TUnit, TOpAssign, flip TIntegerLiteral "1", TRightPar, TEOF ]- shouldBe' (collectF03 "flush(unit=1,iomsg=x,iostat=y,err=z)") $- fmap ($u) [ TFlush, TLeftPar, TUnit, TOpAssign, flip TIntegerLiteral "1", TComma- , TIOMsg, TOpAssign, flip TId "x", TComma- , TIOStat, TOpAssign, flip TId "y", TComma- , TErr, TOpAssign, flip TId "z", TRightPar, TEOF ]-- it "lexes protected" $ do- shouldBe' (collectF03 "real, protected, public :: x") $- fmap ($u) [ TReal, TComma, TProtected, TComma, TPublic, TDoubleColon, flip TId "x", TEOF ]
+ test/Language/Fortran/Parser/Fixed/Fortran66Spec.hs view
@@ -0,0 +1,189 @@+module Language.Fortran.Parser.Fixed.Fortran66Spec ( spec ) where++import Test.Hspec+import TestUtil++import Language.Fortran.AST+import Language.Fortran.Version+import Language.Fortran.Parser+import Language.Fortran.Parser.Monad ( Parse )+import qualified Language.Fortran.Parser.Fixed.Fortran66 as F66+import qualified Language.Fortran.Parser.Fixed.Lexer as Fixed++import Prelude hiding ( LT )+import qualified Data.ByteString.Char8 as B++parseWith :: Parse Fixed.AlexInput Fixed.Token a -> String -> a+parseWith p = parseUnsafe (makeParserFixed p Fortran66) . B.pack++eParser :: String -> Expression ()+eParser = parseUnsafe p . B.pack+ where p = makeParser initParseStateFixedExpr F66.expressionParser Fortran66++sParser :: String -> Statement ()+sParser = parseWith F66.statementParser++spec :: Spec+spec =+ describe "Fortran 66 Parser" $ do+ describe "Expressions" $ do+ describe "Arithmetic expressions" $ do+ it "parses '3'" $ do+ let expectedExp = intGen 3+ eParser "3" `shouldBe'` expectedExp++ it "parses '-3'" $ do+ let expectedExp = ExpUnary () u Minus $ intGen 3+ eParser "-3" `shouldBe'` expectedExp++ it "parses '3 + 2'" $ do+ let expectedExp = ExpBinary () u Addition (intGen 3) (intGen 2)+ eParser "3 + 2" `shouldBe'` expectedExp++ it "parses '3 + -2'" $ do+ let expectedExp = ExpBinary () u Addition (intGen 3) (ExpUnary () u Minus (intGen 2))+ eParser "3 + -2" `shouldBe'` expectedExp++ it "parses '3 + -2 + 42'" $ do+ let expectedExp = ExpBinary () u Addition (ExpBinary () u Addition (intGen 3) (ExpUnary () u Minus (intGen 2))) (intGen 42)+ eParser "3 + -2 + 42" `shouldBe'` expectedExp++ it "parses 'f(y, 24)'" $ do+ let subs = [ IxSingle () u Nothing $ varGen "y", ixSinGen 24 ]+ let expectedExp = ExpSubscript () u (varGen "f") (fromList () subs)+ eParser "f(y, 24)" `shouldBe'` expectedExp++ it "parses '3 + 4 * 12'" $ do+ let expectedExp = ExpBinary () u Addition (intGen 3) (ExpBinary () u Multiplication (intGen 4) (intGen 12))+ eParser "3 + 4 * 12" `shouldBe'` expectedExp++ describe "Logical expressions" $+ it "parses '.true. .and. .false.'" $ do+ let expectedExp = ExpBinary () u And valTrue valFalse+ eParser ".true. .and. .false." `shouldBe'` expectedExp++ describe "Relational expressions" $+ it "parses '(3 * 2) .lt. 42'" $ do+ let expectedExp = ExpBinary () u LT (ExpBinary () u Multiplication (intGen 3) (intGen 2)) (intGen 42)+ eParser "(3 * 2) .lt. 42" `shouldBe'` expectedExp++ describe "Other expressions" $+ it "parses 'a(2 * x - 3, 10)'" $ do+ let firstEl = ExpBinary () u Subtraction (ExpBinary () u Multiplication (intGen 2) (varGen "x")) (intGen 3)+ expectedExp = ExpSubscript () u (varGen "a") (AList () u [ IxSingle () u Nothing firstEl, ixSinGen 10])+ eParser "a(2 * x - 3, 10)" `shouldBe'` expectedExp++ describe "Statements" $ do+ it "parses 'EXTERNAL f, g, h'" $ do+ let procGen s = ExpValue () u (ValVariable s)+ let expectedSt = StExternal () u (AList () u [procGen "f", procGen "g", procGen "h"])+ sParser " EXTERNAL f, g, h" `shouldBe'` expectedSt++ it "parses 'COMMON a, b'" $ do+ let comGr = CommonGroup () u Nothing (AList () u [ declVarGen "a", declVarGen "b" ])+ let st = StCommon () u (AList () u [ comGr ])+ sParser " COMMON a, b" `shouldBe'` st++ it "parses 'COMMON // a, b /hello/ x, y, z'" $ do+ let comGrs = [ CommonGroup () u Nothing (AList () u [ declVarGen "a", declVarGen "b" ])+ , CommonGroup () u (Just $ varGen "hello") (AList () u [ declVarGen "x", declVarGen "y", declVarGen "z" ]) ]+ let st = StCommon () u (AList () u comGrs)+ sParser " COMMON // a, b /hello/ x, y, z" `shouldBe'` st++ it "parses 'EQUIVALENCE (a,b), (x,y,z)'" $ do+ let ls = [ AList () u [varGen "a", varGen "b"]+ , AList () u [varGen "x", varGen "y", varGen "z"] ]+ let st = StEquivalence () u (AList () u ls)+ sParser " EQUIVALENCE (a,b), (x,y,z)" `shouldBe'` st++ it "parses 'DATA a/1,2,3/,x/42/'" $ do+ let dGrs = [ DataGroup () u (AList () u [varGen "a"]) (AList () u [intGen 1, intGen 2, intGen 3])+ , DataGroup () u (AList () u [varGen "x"]) (AList () u [intGen 42]) ]+ let st = StData () u $ AList () u dGrs+ sParser " DATA a/1,2,3/, x/42/" `shouldBe'` st++ describe "FORMAT" $ do+ it "parses 'FORMAT ()'" $ do+ let expectedSt = StFormatBogus () u "()"+ sParser " FORMAT ()" `shouldBe'` expectedSt++ it "parses 'FORMAT (///)'" $ do+ let expectedSt = StFormatBogus () u "(///)"+ sParser " FORMAT (///)" `shouldBe'` expectedSt++ it "parses 'FORMAT (2i5/5hhello)'" $ do+ let expectedSt = StFormatBogus () u "(2i5/5hhello)"+ sParser " FORMAT (2i5/5hhello)" `shouldBe'` expectedSt++ it "parses 'FORMAT (/(i5))'" $ do+ let expectedSt = StFormatBogus () u "(/(i5))"+ sParser " FORMAT (/(i5))" `shouldBe'` expectedSt++ describe "CALL" $ do+ it "parses 'CALL me" $ do+ let expectedSt = StCall () u (ExpValue () u (ValVariable "me")) Nothing+ sParser " CALL me" `shouldBe'` expectedSt++ it "parses 'CALL me(baby)" $ do+ let args = AList () u [ Argument () u Nothing $ ArgExpr $ varGen "baby" ]+ let expectedSt = StCall () u (ExpValue () u (ValVariable "me")) $ Just args+ sParser " CALL me(baby)" `shouldBe'` expectedSt++ it "parses 'stop'" $ do+ let expectedSt = StStop () u Nothing+ sParser " stop" `shouldBe'` expectedSt++ it "parses 'integer i, j(2,2), k'" $ do+ let dimDecls = replicate 2 $ DimensionDeclarator () u Nothing (Just $ intGen 2)+ declarators = [ Declarator () u (varGen "i") ScalarDecl Nothing Nothing+ , Declarator () u (varGen "j") (ArrayDecl (AList () u dimDecls)) Nothing Nothing+ , Declarator () u (varGen "k") ScalarDecl Nothing Nothing ]+ st = StDeclaration () u (TypeSpec () u TypeInteger Nothing) Nothing $ AList () u declarators+ sParser " integer i, j(2,2), k" `shouldBe'` st++ let controlPairs = AList () u [ ControlPair () u Nothing (intGen 6), ControlPair () u Nothing (labelGen 10) ]+ let writeSt = StWrite () u controlPairs (Just $ AList () u [ varGen "i" ])++ describe "WRITE" $ do+ it "parses 'write (6)'" $ do+ let expectedSt = StWrite () u (AList () u [ ControlPair () u Nothing (intGen 6) ]) Nothing+ sParser " write (6)" `shouldBe'` expectedSt++ it "parses 'write (6) i'" $ do+ let expectedSt = StWrite () u (AList () u [ ControlPair () u Nothing (intGen 6) ]) (Just $ AList () u [ varGen "i" ])+ sParser " write (6) i" `shouldBe'` expectedSt++ it "parses 'write (6,10) i'" $+ sParser " write (6,10) i" `shouldBe'` writeSt++ describe "IF" $ do+ it "parses 'if (10 .LT. x) write (6,10) i'" $ do+ let cond = ExpBinary () u LT (intGen 10) (varGen "x")+ let expectedSt = StIfLogical () u cond writeSt+ sParser " if (10 .LT. x) write (6,10) i" `shouldBe'` expectedSt++ it "parses 'if (10 - 5) 10, 20, 30'" $ do+ let cond = ExpBinary () u Subtraction (intGen 10) (intGen 5)+ let expectedSt = StIfArithmetic () u cond (labelGen 10) (labelGen 20) (labelGen 30)+ sParser " if (10 - 5) 10, 20, 30" `shouldBe'` expectedSt++ it "parses 'IF (IY) 5,6,6" $ do+ let expectedSt = StIfArithmetic () u (varGen "iy") (labelGen 5) (labelGen 6) (labelGen 6)+ sParser " IF (IY) 5,6,6" `shouldBe'` expectedSt++ describe "ASSIGNMENT" $ do+ it "parses 'f = 1'" $ do+ let expectedSt = StExpressionAssign () u (varGen "f") (intGen 1)+ sParser " f = 1" `shouldBe'` expectedSt++ it "parses 'f = a(1,2)'" $ do+ let indicies = fromList () [ ixSinGen 1, ixSinGen 2 ]+ let rhs = ExpSubscript () u (varGen "a") indicies+ let expectedSt = StExpressionAssign () u (varGen "f") rhs+ sParser " f = a(1,2)" `shouldBe'` expectedSt++ it "parses 'do 42 i = 10, 1, 1'" $ do+ let st = StExpressionAssign () u (varGen "i") (intGen 10)+ let doSpec = DoSpecification () u st (intGen 1) (Just $ intGen 1)+ let expectedSt = StDo () u Nothing (Just $ labelGen 42) (Just doSpec)+ sParser " do 42 i = 10, 1, 1" `shouldBe'` expectedSt
+ test/Language/Fortran/Parser/Fixed/Fortran77/IncludeSpec.hs view
@@ -0,0 +1,52 @@+module Language.Fortran.Parser.Fixed.Fortran77.IncludeSpec where++import System.FilePath+import Test.Hspec+import TestUtil++import Language.Fortran.Parser ( f77lIncludes )+import Language.Fortran.AST+import Language.Fortran.Util.Position+import qualified Data.ByteString.Char8 as B++iParser :: [String] -> String -> IO (ProgramFile A0)+iParser incs = f77lIncludes incs mempty "<unknown>" . B.pack++makeSrcR :: (Int, Int, Int, String) -> (Int, Int, Int, String) -> SrcSpan+makeSrcR (i1, i2, i3, s) (j1, j2, j3, s') = SrcSpan (Position i1 i2 i3 s Nothing) (Position j1 j2 j3 s' Nothing)++spec :: SpecWith ()+spec =+ describe "Include Test" $ do+ let source = unlines [" program bar",+ " include 'foo.f'",+ " end"+ ]+ inc = "./test-data/f77-include"+ name = "bar"+ pf = ProgramFile mi77' [pu]+ puSpan = makeSrcR (6,7,1,"<unknown>") (48,9,3,"<unknown>")+ st1Span = makeSrcR (24,7,2,"<unknown>") (38,21,2,"<unknown>")+ expSpan = makeSrcR (32,15,2,"<unknown>") (38,21,2,"<unknown>")++ -- the expansion returns the span in the included file+ -- it should return the span at the inclusion+ foo = inc </> "foo.f"+ st2Span = makeSrcR (6,7,1, foo) (14,15,1,foo)+ declSpan = makeSrcR (6,7,1,foo) (14,15,1,foo)+ typeSpan = makeSrcR (6,7,1,foo) (12,13,1,foo)+ blockSpan = makeSrcR (14,15,1,foo) (14,15,1,foo)+ varGen' str = ExpValue () blockSpan $ ValVariable str++ pu = PUMain () puSpan (Just name) blocks Nothing+ blocks = [bl1]+ decl = Declarator () blockSpan (varGen' "a") ScalarDecl Nothing Nothing+ typeSpec = TypeSpec () typeSpan TypeInteger Nothing+ st2 = StDeclaration () st2Span typeSpec Nothing (AList () blockSpan [decl])+ bl1 = BlStatement () st1Span Nothing st1+ st1 = StInclude () st1Span ex (Just [bl2])+ ex = ExpValue () expSpan (ValString "foo.f")+ bl2 = BlStatement () declSpan Nothing st2+ it "includes some files and expands them" $ do+ pfParsed <- iParser [inc] source+ pfParsed `shouldBe` pf
+ test/Language/Fortran/Parser/Fixed/Fortran77/ParserSpec.hs view
@@ -0,0 +1,412 @@+module Language.Fortran.Parser.Fixed.Fortran77.ParserSpec where++import Test.Hspec+import TestUtil++import Language.Fortran.AST+import Language.Fortran.Version+import Language.Fortran.Parser+import Language.Fortran.Parser.Monad ( Parse )+import qualified Language.Fortran.Parser.Fixed.Fortran77 as F77+import qualified Language.Fortran.Parser.Fixed.Lexer as Fixed++import Prelude hiding ( exp )+import qualified Data.ByteString.Char8 as B++parseWith :: FortranVersion -> Parse Fixed.AlexInput Fixed.Token a -> String -> a+parseWith fv p = parseUnsafe (makeParserFixed p fv) . B.pack++pParser :: String -> ProgramFile ()+pParser = parseWith Fortran77 F77.programParser++bParser :: String -> Block ()+bParser = parseWith Fortran77Legacy F77.blockParser++sParser :: String -> Statement ()+sParser = parseWith Fortran77 F77.statementParser++eParser :: String -> Expression ()+eParser = parseUnsafe p . B.pack+ where p = makeParser initParseStateFixedExpr F77.expressionParser Fortran77++plParser :: String -> ProgramFile ()+plParser = parseWith Fortran77Legacy F77.programParser++slParser :: String -> Statement ()+slParser = parseWith Fortran77Legacy F77.statementParser++spec :: Spec+spec =+ describe "Fortran 77 Parser" $ do+ describe "IO" $ do+ it "parses 'print *, 9000" $ do+ let expectedSt = StPrint () u starVal $ Just (AList () u [ intGen 9000 ])+ sParser " print *, 9000" `shouldBe'` expectedSt++ it "parses 'write (UNIT=6, FORMAT=*)" $ do+ let cp1 = ControlPair () u (Just "unit") (intGen 6)+ cp2 = ControlPair () u (Just "format") starVal+ expectedSt = StWrite () u (AList () u [cp1, cp2]) Nothing+ sParser " write (UNIT=6, FORMAT=*)" `shouldBe'` expectedSt++ it "parses 'endfile i" $+ sParser " endfile i" `shouldBe'` StEndfile2 () u (varGen "i")++ it "parses 'read *, (x, y(i), i = 1, 10, 2)'" $ do+ let stAssign = StExpressionAssign () u (varGen "i") (intGen 1)+ doSpec = DoSpecification () u stAssign (intGen 10) (Just $ intGen 2)+ impliedDoVars = AList () u [ varGen "x", ExpSubscript () u (varGen "y") (AList () u [ IxSingle () u Nothing $ varGen "i" ])]+ impliedDo = ExpImpliedDo () u impliedDoVars doSpec+ iolist = AList () u [ impliedDo ]+ expectedSt = StRead2 () u starVal (Just iolist)+ sParser " read *, (x, y(i), i = 1, 10, 2)" `shouldBe'` expectedSt++ it "parses '(x, y(i), i = 1, 10, 2)'" $ do+ let stAssign = StExpressionAssign () u (varGen "i") (intGen 1)+ doSpec = DoSpecification () u stAssign (intGen 10) (Just $ intGen 2)+ impliedDoVars = AList () u [ varGen "x", ExpSubscript () u (varGen "y") (AList () u [ IxSingle () u Nothing $ varGen "i" ])]+ impliedDo = ExpImpliedDo () u impliedDoVars doSpec+ eParser "(x, y(i), i = 1, 10, 2)" `shouldBe'` impliedDo++ it "parses main program unit" $ do+ let decl = declVarGen "x"+ st = StDeclaration () u (TypeSpec () u TypeInteger Nothing) Nothing (AList () u [ decl ])+ bl = BlStatement () u Nothing st+ pu = ProgramFile mi77 [ PUMain () u (Just "hello") [ bl ] Nothing ]+ pParser exampleProgram1 `shouldBe'` pu++ it "parses block data unit" $ do+ let decl = declVarGen "x"+ st = StDeclaration () u (TypeSpec () u TypeInteger Nothing) Nothing (AList () u [ decl ])+ bl = BlStatement () u Nothing st+ pu = ProgramFile mi77 [ PUBlockData () u (Just "hello") [ bl ] ]+ pParser exampleProgram2 `shouldBe'` pu++ it "parses 'intrinsic cosh, sin'" $ do+ let st = StIntrinsic () u (AList () u [ varGen "cosh", varGen "sin" ])+ sParser " intrinsic cosh, sin" `shouldBe'` st++ it "parses 'intrinsic real" $ do+ let st = StIntrinsic () u (AList () u [ varGen "real" ])+ sParser " intrinsic real" `shouldBe'` st++ describe "CHARACTER" $ do+ it "parses character literal assignment" $ do+ let rhs = ExpValue () u (ValString "hello 'baby")+ st = StExpressionAssign () u (varGen "xyz") rhs+ sParser " xyz = 'hello ''baby'" `shouldBe'` st++ it "string concatenation" $ do+ let str1 = ExpValue () u (ValString "hello ")+ str2 = ExpValue () u (ValString "world")+ exp = ExpBinary () u Concatenation str1 str2+ eParser "'hello ' // 'world'" `shouldBe'` exp++ describe "Subscript like" $ do+ it "parses vanilla subscript" $ do+ let exp = ExpSubscript () u (varGen "a") (AList () u [ IxSingle () u Nothing $ varGen "x", IxSingle () u Nothing $ intGen 2, IxSingle () u Nothing $ intGen 3 ])+ eParser "a(x, 2, 3)" `shouldBe'` exp++ it "parses array declarator" $ do+ let dimDecls = [ DimensionDeclarator () u (Just $ intGen 1) (Just $ intGen 2)+ , DimensionDeclarator () u Nothing (Just $ intGen 15)+ , DimensionDeclarator () u (Just $ varGen "x") (Just starVal) ]+ decl = declArray () u (varGen "a") (AList () u dimDecls) Nothing Nothing+ st = StDeclaration () u (TypeSpec () u TypeInteger Nothing) Nothing (AList () u [ decl ])+ sParser " integer a(1:2, 15, x:*)" `shouldBe'` st++ it "parses character substring" $ do+ let indicies = [ ixSinGen 1, ixSinGen 2, ixSinGen 3 ]+ subExp = ExpSubscript () u (varGen "a") (AList () u indicies)+ range = IxRange () u Nothing (Just $ intGen 10) Nothing+ exp = ExpSubscript () u subExp (AList () u [ range ])+ eParser "a(1, 2, 3)(:10)" `shouldBe'` exp++ it "parses simpler substring" $ do+ let exp = ExpSubscript () u (varGen "a") (AList () u [ ixRanGen 5 10 ])+ eParser "a(5:10)" `shouldBe'` exp++ it "parses simpler substring" $ do+ let range = IxRange () u (Just $ intGen 5) Nothing Nothing+ exp = ExpSubscript () u (varGen "a") (AList () u [ range ])+ eParser "a(5:)" `shouldBe'` exp++ it "parses literal string subscript" $ do+ let range = IxRange () u (Just $ intGen 1) (Just $ intGen 2) Nothing+ exp = ExpSubscript () u (strGen "abc") (AList () u [ range ])+ eParser "'abc'(1:2)" `shouldBe'` exp++ describe "GOTO" $ do+ it "parses computed GOTO with integer expression" $ do+ let exp = ExpBinary () u Multiplication (intGen 42) (intGen 24)+ st = StGotoComputed () u (AList () u [labelGen 10, labelGen 20, labelGen 30]) exp+ sParser " GOTO (10, 20, 30), 42 * 24" `shouldBe'` st++ let gotoSt = StGotoAssigned () u (varGen "v") (Just (AList () u [labelGen 10, labelGen 20, labelGen 30]))+ it "parses assigned GOTO with comma" $+ sParser " GOTO v, (10, 20, 30)" `shouldBe'` gotoSt++ it "parses assigned GOTO without comma" $+ sParser " GOTO v (10, 20, 30)" `shouldBe'` gotoSt++ describe "IMPLICIT" $ do+ it "parses 'implicit none'" $ do+ let st = resetSrcSpan $ StImplicit () u Nothing+ sParser " implicit none" `shouldBe'` st++ it "parses 'implicit character*30 (a, b, c), integer (a-z, l)" $ do+ let impEls = [ImpCharacter () u "a", ImpCharacter () u "b", ImpCharacter () u "c"]+ sel = Selector () u (Just (intGen 30)) Nothing+ imp1 = ImpList () u (TypeSpec () u TypeCharacter (Just sel)) $ AList () u impEls+ imp2 = ImpList () u (TypeSpec () u TypeInteger Nothing) $ AList () u [ImpRange () u "a" "z", ImpCharacter () u "l"]+ st = StImplicit () u $ Just $ AList () u [imp1, imp2]+ sParser " implicit character*30 (a, b, c), integer (a-z, l)" `shouldBe'` st++ it "parses 'parameter (pi = 3.14, b = 'X' // 'O', d = k) '" $ do+ let sts = [ declVariable () u (varGen "pi") Nothing (Just $ realGen (3.14::Double))+ , let e = ExpBinary () u Concatenation (strGen "X") (strGen "O")+ in declVariable () u (varGen "b") Nothing (Just e)+ , declVariable () u (varGen "d") Nothing (Just $ varGen "k") ]+ st = StParameter () u (AList () u sts)+ sParser " parameter (pi = 3.14, b = 'X' // 'O', d = k)" `shouldBe'` st++ it "parses 'pause 'hello world''" $ do+ let st = StPause () u $ Just $ strGen "hello world"+ sParser " pause 'hello world'" `shouldBe'` st++ describe "SAVE" $ do+ it "parses 'save /cb/, var, /key/'" $ do+ let saveArgs = [ varGen "cb", varGen "var", varGen "key" ]+ st = StSave () u (Just $ AList () u saveArgs)+ sParser " save /cb/, var, /key/" `shouldBe'` st++ it "parses 'save'" $+ sParser " save" `shouldBe'` StSave () u Nothing++ it "parses '.true. .eqv. f(42) .neqv. x'" $ do+ let arg2 = ExpSubscript () u (varGen "f") $ AList () u [ ixSinGen 42 ]+ arg3 = varGen "x"+ subexp = ExpBinary () u Equivalent valTrue arg2+ exp = ExpBinary () u NotEquivalent subexp arg3+ eParser ".true. .eqv. f(42) .neqv. x" `shouldBe'` exp++ it "parses 'entry me (a,b,*)'" $ do+ let args = [ varGen "a", varGen "b", starVal ]+ st = StEntry () u (varGen "me") (Just $ AList () u args) Nothing+ sParser " entry me (a,b,*)" `shouldBe'` st++ it "parses 'character a*8'" $ do+ let decl = declVariable () u (varGen "a") (Just $ intGen 8) Nothing+ typeSpec = TypeSpec () u TypeCharacter Nothing+ st = StDeclaration () u typeSpec Nothing (AList () u [ decl ])+ sParser " character a*8" `shouldBe'` st++ it "parses 'character c*(ichar('A'))" $ do+ let args = AList () u [ IxSingle () u Nothing (ExpValue () u (ValString "A")) ]+ lenExpr = ExpSubscript () u (varGen "ichar") args+ decl = declVariable () u (varGen "c") (Just $ lenExpr) Nothing+ typeSpec = TypeSpec () u TypeCharacter Nothing+ st = StDeclaration () u typeSpec Nothing (AList () u [ decl ])+ sParser " character c*(ichar('A'))" `shouldBe'` st++ describe "parses if blocks" $ do+ let printArgs = Just $ AList () u [ExpValue () u $ ValString "foo"]+ printStmt = StPrint () u (ExpValue () u ValStar) printArgs+ printBlock = BlStatement () u Nothing printStmt+ it "unlabelled" $ do+ let bl = BlIf () u Nothing Nothing [ Just valTrue, Nothing ] [[printBlock], [printBlock]] Nothing+ src = unlines [ " if (.true.) then ! comment if"+ , " print *, 'foo'"+ , " else ! comment else"+ , " print *, 'foo'"+ , " endif ! comment end"+ ]+ bParser src `shouldBe'` bl+ it "labelled" $ do+ let label = Just . intGen+ bl = BlIf () u (label 10) Nothing [Just valTrue, Nothing] [[printBlock], [printBlock]] (label 30)+ src = unlines [ "10 if (.true.) then ! comment if"+ , " print *, 'foo'"+ , "20 else ! comment else"+ , " print *, 'foo'"+ , "30 endif ! comment end"+ ]+ bParser src `shouldBe'` bl++ describe "Legacy Extensions" $ do+ it "parses structure/union/map blocks" $ do+ let src = init+ $ unlines [ " structure /foo/"+ , " union"+ , " map"+ , " integer i"+ , " end map"+ , " map"+ , " real r"+ , " end map"+ , " end union"+ , " end structure"]+ ds = [ UnionMap () u $ AList () u+ [StructFields () u (TypeSpec () u TypeInteger Nothing) Nothing $+ AList () u [declVariable () u (varGen "i") Nothing Nothing]]+ , UnionMap () u $ AList () u+ [StructFields () u (TypeSpec () u TypeReal Nothing) Nothing $+ AList () u [declVariable () u (varGen "r") Nothing Nothing]]+ ]+ st = StStructure () u (Just "foo") $ AList () u [StructUnion () u $ AList () u ds]+ resetSrcSpan (slParser src) `shouldBe` st++ it "parses structure/union/map blocks with comments" $ do+ let src = init+ $ unlines [ " structure /foo/"+ , "C comment before union"+ , " union"+ , "C comment inside union, before map"+ , " map"+ , "C comment inside map"+ , " integer i ! more comment"+ , " end map"+ , "C comment between maps"+ , " map"+ , " real r ! more comment"+ , " end map"+ , "C comment after map"+ , " end union"+ , "C comment after union"+ , " end structure"]+ ds = [ UnionMap () u $ AList () u+ [StructFields () u (TypeSpec () u TypeInteger Nothing) Nothing $+ AList () u [declVariable () u (varGen "i") Nothing Nothing]]+ , UnionMap () u $ AList () u+ [StructFields () u (TypeSpec () u TypeReal Nothing) Nothing $+ AList () u [declVariable () u (varGen "r") Nothing Nothing]]+ ]+ st = StStructure () u (Just "foo") $ AList () u [StructUnion () u $ AList () u ds]+ resetSrcSpan (slParser src) `shouldBe` st++ it "parses nested structure blocks" $ do+ let src = init+ $ unlines [ " structure /foo/"+ , " structure /bar/ baz"+ , " integer qux"+ , " end structure"+ , " end structure"]+ var = declVariable () u (varGen "qux") Nothing Nothing+ innerst = StructStructure () u (Just "bar") ("baz")+ $ AList () u [StructFields () u (TypeSpec () u TypeInteger Nothing) Nothing+ $ AList () u [var]]+ st = StStructure () u (Just "foo") $ AList () u [innerst]+ resetSrcSpan (slParser src) `shouldBe` st++ it "parses structure data references " $ do+ let st = StPrint () u expStar $ Just $ AList () u [foobar]+ foobar = ExpDataRef () u (varGen "foo") (varGen "bar")+ expStar = ExpValue () u ValStar+ sParser " print *, foo % bar" `shouldBe'` st+ sParser " print *, foo.bar" `shouldBe'` st++ it "parse special intrinsics to arguments" $ do+ let blStmt stmt = BlStatement () u Nothing stmt+ ext = blStmt $ StExternal () u $ AList () u [varGen "bar"]+ arg = Just . AList () u . pure . Argument () u Nothing . ArgExpr+ valBar = ExpFunctionCall () u (ExpValue () u (ValIntrinsic "%val"))+ $ arg $ varGen "baz"+ call = blStmt $ StCall () u (varGen "bar") $ arg valBar+ pu = ProgramFile mi77 [ PUSubroutine () u (Nothing, Nothing) "foo"+ (Just $ AList () u [varGen "baz"]) [ ext, call ] Nothing ]+ resetSrcSpan (plParser exampleProgram3) `shouldBe` pu++ it "parses character declarations with unspecfied lengths" $ do+ let src = " character s*(*)"+ st = StDeclaration () u (TypeSpec () u TypeCharacter Nothing) Nothing $+ AList () u [declVariable () u+ (varGen "s")+ (Just (ExpValue () u ValStar))+ Nothing]+ resetSrcSpan (slParser src) `shouldBe` st++ it "parses array initializers" $ do+ let src = " integer xs(3) / 1, 2, 3 /"+ inits = [intGen 1, intGen 2, intGen 3]+ st = StDeclaration () u (TypeSpec () u TypeInteger Nothing) Nothing $+ AList () u [declArray () u+ (varGen "xs")+ (AList () u [DimensionDeclarator () u Nothing (Just (intGen 3))])+ Nothing+ (Just (ExpInitialisation () u $ AList () u inits))]+ resetSrcSpan (slParser src) `shouldBe` st++ let src1 = " character xs(2)*5 / 'hello', 'world' /"+ inits1 = [ExpValue () u (ValString "hello"), ExpValue () u (ValString "world")]+ st1 = StDeclaration () u (TypeSpec () u TypeCharacter Nothing) Nothing $+ AList () u [declArray () u+ (varGen "xs")+ (AList () u [DimensionDeclarator () u Nothing (Just (intGen 2))])+ (Just (intGen 5))+ (Just (ExpInitialisation () u $ AList () u inits1))]+ resetSrcSpan (slParser src1) `shouldBe` st1++ let src2 = " character xs*5(2) / 'hello', 'world' /"+ inits2 = [ExpValue () u (ValString "hello"), ExpValue () u (ValString "world")]+ st2 = StDeclaration () u (TypeSpec () u TypeCharacter Nothing) Nothing $+ AList () u [declArray () u+ (varGen "xs")+ (AList () u [DimensionDeclarator () u Nothing (Just (intGen 2))])+ (Just (intGen 5))+ (Just (ExpInitialisation () u $ AList () u inits2))]+ resetSrcSpan (slParser src2) `shouldBe` st2++ it "parses subscripts in assignments" $ do+ let mkIdx i = IxSingle () u Nothing (intGen i)++ src = " x(0,1) = 0"+ tgt = ExpSubscript () u (varGen "x") (AList () u [mkIdx 0, mkIdx 1])+ st = StExpressionAssign () u tgt (intGen 0)+ resetSrcSpan (slParser src) `shouldBe` st++ let src1 = " x(0).foo = 0"+ tgt1 = ExpDataRef () u (ExpSubscript () u (varGen "x") (AList () u [mkIdx 0])) (varGen "foo")+ st1 = StExpressionAssign () u tgt1 (intGen 0)+ resetSrcSpan (slParser src1) `shouldBe` st1++ let src2 = " x.foo = 0"+ tgt2 = ExpDataRef () u (varGen "x") (varGen "foo")+ st2 = StExpressionAssign () u tgt2 (intGen 0)+ resetSrcSpan (slParser src2) `shouldBe` st2++ let src3 = " x.foo(0) = 0"+ tgt3 = ExpSubscript () u (ExpDataRef () u (varGen "x") (varGen "foo")) (AList () u [mkIdx 0])+ st3 = StExpressionAssign () u tgt3 (intGen 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+ [ " program hello"+ , " integer x"+ , " end" ]++exampleProgram2 :: String+exampleProgram2 = unlines+ [ " 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+-- haskell-program-name: "cabal repl test-suite:spec"+-- End:
+ test/Language/Fortran/Parser/Fixed/LexerSpec.hs view
@@ -0,0 +1,324 @@+module Language.Fortran.Parser.Fixed.LexerSpec where++import Test.Hspec+import Test.Hspec.QuickCheck+import TestUtil++import Language.Fortran.Parser.Fixed.Lexer+import Language.Fortran.Parser+import Language.Fortran.Parser.Monad ( ParseState, getAlex, evalParse )+import Language.Fortran.AST.Boz+import Language.Fortran.Version++import Data.List (isPrefixOf)+import qualified Data.ByteString.Char8 as B++initState :: FortranVersion -> B.ByteString -> ParseState AlexInput+initState = initParseStateFixed "<unknown>"++collectFixedTokens :: FortranVersion -> B.ByteString -> [Token]+collectFixedTokens fv bs =+ collectTokens lexer' $ initState fv bs++collectFixedTokens' :: FortranVersion -> String -> [Token]+collectFixedTokens' v = collectFixedTokens v . B.pack++collectFixedTokensSafe :: FortranVersion -> B.ByteString -> Maybe [Token]+collectFixedTokensSafe fv bs =+ collectTokensSafe lexer' $ initState fv bs++lex66 :: String -> Maybe Token+lex66 = collectToLex Fortran66++safeLex66 :: String -> Maybe Token+safeLex66 = collectToLexSafe Fortran66++lex77 :: String -> Maybe Token+lex77 = collectToLex Fortran77++collectToLex :: FortranVersion -> String -> Maybe Token+collectToLex version srcInput = dropUntil2 $ collectFixedTokens version (B.pack srcInput)+ where+ dropUntil2 [] = Nothing+ dropUntil2 [_] = Nothing+ dropUntil2 [a,_] = Just a+ dropUntil2 (_:xs) = dropUntil2 xs++collectToLexSafe :: FortranVersion -> String -> Maybe Token+collectToLexSafe version srcInput = dropUntil2 $ collectFixedTokensSafe version (B.pack srcInput)+ where+ dropUntil2 (Just [a,_]) = Just a+ dropUntil2 (Just (_:xs)) = dropUntil2 $ Just xs+ dropUntil2 _ = Nothing++spec :: Spec+spec =+ describe "Fortran Fixed Form Lexer" $ do+ describe "Fortran 77" $+ describe "String" $ do+ it "lexes 'hello'" $+ resetSrcSpan (lex77 " c = 'hello'") `shouldBe` resetSrcSpan (Just $ TString u "hello")++ it "lexes 'he''llo'" $+ resetSrcSpan (lex77 " c = 'he''llo'") `shouldBe` resetSrcSpan (Just $ TString u "he'llo")++ it "lexes 'he''''ll''o'" $+ resetSrcSpan (lex77 " c = 'he''''ll''o'") `shouldBe` resetSrcSpan (Just $ TString u "he''ll'o")++ it "lexes '''hello'''" $+ resetSrcSpan (lex77 " c = '''hello'''") `shouldBe` resetSrcSpan (Just $ TString u "'hello'")++ it "lexes 'hello world'" $+ resetSrcSpan (lex77 " c = 'hello world'") `shouldBe` resetSrcSpan (Just $ TString u "hello world")++ it "lexes 'hello world'" $+ resetSrcSpan (collectFixedTokens' Fortran77 " c = 'x' // 'o'") `shouldBe` resetSrcSpan [TId u "c", TOpAssign u, TString u "x", TSlash u, TSlash u, TString u "o", TEOF u]++ describe "Fortran 66" $ do+ prop "lexes Label, Comment, Newline or EOF in the first six columns or returns Nothing " $+ \x -> isPrefixOf " " x || case safeLex66 x of+ Nothing -> True+ Just (TLabel _ _) -> True+ Just (TComment _ _) -> True+ Just (TEOF _) -> True+ Just (TNewline _) -> True+ _ -> False++ it "lexes alphanumeric identifier" $+ resetSrcSpan (collectFixedTokens' Fortran66 " e42 =") `shouldBe` resetSrcSpan [TId u "e42", TOpAssign u, TEOF u]++ it "lexes exponent" $+ resetSrcSpan (collectFixedTokens' Fortran66 " a = 42 e42") `shouldBe` resetSrcSpan [TId u "a", TOpAssign u, TInt u "42", TExponent u "e42", TEOF u]++ it "lexes 'function foo()'" $+ resetSrcSpan (collectFixedTokens' Fortran66 " function foo()") `shouldBe` resetSrcSpan [TFunction u, TId u "foo", TLeftPar u, TRightPar u, TEOF u]++ it "lexes 'end'" $+ resetSrcSpan (lex66 " end") `shouldBe` resetSrcSpan (Just $ TEnd u)++ it "lexes identifier" $+ resetSrcSpan (lex66 " a = mistr") `shouldBe` resetSrcSpan (Just $ TId u "mistr")++ it "lexes comment if first column is C" $+ resetSrcSpan (lex66 "c this is a comment") `shouldBe` resetSrcSpan (Just $ TComment u " this is a comment")++ it "lexes empty comment" $+ resetSrcSpan (lex66 "c") `shouldBe` resetSrcSpan (Just $ TComment u "")++ it "lexes comment with one char" $+ resetSrcSpan (lex66 "ca") `shouldBe` resetSrcSpan (Just $ TComment u "a")++ it "should not lex from the next line" $+ resetSrcSpan (safeLex66 "cxxx\nselam") `shouldNotBe` resetSrcSpan (Just $ TComment u "xxxselam")++ -- This is commented out as identifiers are longer than what the standard says.+ it "lexes three tokens" $ do+ pending+ resetSrcSpan (collectFixedTokens' Fortran66 " function end format") `shouldBe` resetSrcSpan [TFunction u, TId u "endfor", TId u "mat", TEOF u]++ it "lexes multiple comments in a line" $+ resetSrcSpan (collectFixedTokens' Fortran66 "csomething\ncsomething else\n\nc\ncc\n") `shouldBe`+ resetSrcSpan [TComment u "something", TNewline u, TComment u "something else", TNewline u, TNewline u, TComment u "", TNewline u, TComment u "c", TNewline u, TEOF u]++ it "lexes example1" $+ resetSrcSpan (collectFixedTokens' Fortran66 example1) `shouldBe` resetSrcSpan example1Expectation++ it "lexes end of file" $+ resetSrcSpan (lex66 "") `shouldBe` Nothing++ it "lexes '3 + 2'" $+ resetSrcSpan (collectFixedTokens' Fortran66 " a = 3 + 2") `shouldBe` resetSrcSpan [TId u "a", TOpAssign u, TInt u "3", TOpPlus u , TInt u "2", TEOF u]++ it "should lex continuation lines properly" $+ resetSrcSpan (collectFixedTokens' Fortran66 continuationExample) `shouldBe` resetSrcSpan [ TType u "integer", TId u "ix", TNewline u, TId u "ix", TOpAssign u, TInt u "42", TNewline u, TEnd u, TNewline u, TEOF u ]++ it "lexes 'ASSIGN 100 TO FOO'" $+ resetSrcSpan (collectFixedTokens' Fortran66 " ASSIGN 100 TO FOO") `shouldBe` resetSrcSpan [TAssign u, TInt u "100", TTo u, TId u "foo", TEOF u]++ it "lexes 'DO 100 dovar = 1, 10'" $+ resetSrcSpan (collectFixedTokens' Fortran66 " DO 100 dovar = 1, 10")+ `shouldBe`+ resetSrcSpan [TDo u, TInt u "100", TId u "dovar", TOpAssign u, TInt u "1", TComma u, TInt u "10", TEOF u]++ describe "lexN" $+ it "`lexN 5` parses lexes next five characters" $+ (lexemeMatch . aiLexeme) (evalParse (lexN 5 >> getAlex) (initState Fortran66 (B.pack "helloWorld"))) `shouldBe` reverse "hello"++ describe "lexHollerith" $ do+ it "lexes Hollerith '7hmistral'" $+ resetSrcSpan (lex66 " x = 7hmistral") `shouldBe` resetSrcSpan (Just $ THollerith u "mistral")++ it "becomes case sensitive" $+ resetSrcSpan (collectFixedTokens' Fortran66 " format (5h a= 1)") `shouldBe` resetSrcSpan [ TFormat u, TBlob u "(5ha=1)", TEOF u ]++ it "lexes if statement ' IF (IY) 5,6,6'" $+ resetSrcSpan (collectFixedTokens' Fortran66 " IF (IY) 5,6,6") `shouldBe` resetSrcSpan [TIf u, TLeftPar u, TId u "iy", TRightPar u, TInt u "5", TComma u, TInt u "6", TComma u, TInt u "6", TEOF u]++ it "lexes if then statement ' if (x) then'" $+ resetSrcSpan (collectFixedTokens' Fortran77 " if (x) then") `shouldBe` resetSrcSpan [TIf u, TLeftPar u, TId u "x", TRightPar u, TThen u, TEOF u]++ it "lexes if variable decl ' INTEGER IF'" $ -- yes, really..+ resetSrcSpan (collectFixedTokens' Fortran77 " INTEGER IF")+ `shouldBe` resetSrcSpan [TType u "integer", TId u "if", TEOF u]++ describe "Fortran 77 Legacy" $ do+ it "lexes inline comments" $+ resetSrcSpan (collectFixedTokens' Fortran77Legacy " integer foo ! bar")+ `shouldBe` resetSrcSpan [TType u "integer", TId u "foo", TEOF u]++ it "lexes continuation lines separated by comments" $ do+ let src = unlines [ " integer foo,"+ , "C hello"+ , " + bar"+ ]+ in resetSrcSpan (collectFixedTokens' Fortran77Legacy src)+ `shouldBe` resetSrcSpan [TType u "integer", TId u "foo", TComma u, TId u "bar", TNewline u, TEOF u]+ let src = unlines [ " integer foo, ! hello"+ , " + bar"+ ]+ in resetSrcSpan (collectFixedTokens' Fortran77Legacy src)+ `shouldBe` resetSrcSpan [TType u "integer", TId u "foo", TComma u, TId u "bar", TNewline u, TEOF u]+ let src = unlines [ " integer foo,"+ , ""+ , " + bar"+ ]+ in resetSrcSpan (collectFixedTokens' Fortran77Legacy src)+ `shouldBe` resetSrcSpan [TType u "integer", TId u "foo", TComma u, TId u "bar", TNewline u, TEOF u]+ let src = unlines [ " integer foo,"+ , " " -- the space is intentional+ , " + bar"+ ]+ in resetSrcSpan (collectFixedTokens' Fortran77Legacy src)+ `shouldBe` resetSrcSpan [TType u "integer", TId u "foo", TComma u, TId u "bar", TNewline u, TEOF u]++ it "lexes the older TYPE statement" $+ resetSrcSpan (collectFixedTokens' Fortran77Legacy " type *, 'hello'")+ `shouldBe` resetSrcSpan [TTypePrint u, TStar u, TComma u, TString u "hello", TEOF u]++ it "lexes width-specific type declarations" $ do+ resetSrcSpan (collectFixedTokens' Fortran77Legacy " integer*4 i")+ `shouldBe` resetSrcSpan [TType u "integer", TStar u, TInt u "4", TId u "i", TEOF u]++ resetSrcSpan (collectFixedTokens' Fortran77Legacy " integer*4 function foo()")+ `shouldBe` resetSrcSpan [TType u "integer", TStar u, TInt u "4", TFunction u, TId u "foo", TLeftPar u, TRightPar u, TEOF u]++ resetSrcSpan (collectFixedTokens' Fortran77Legacy " character*4 s")+ `shouldBe` resetSrcSpan [TType u "character", TStar u, TInt u "4", TId u "s", TEOF u]++ resetSrcSpan (collectFixedTokens' Fortran77Legacy " character*(*) s")+ `shouldBe` resetSrcSpan [TType u "character", TStar u, TLeftPar u, TStar u, TRightPar u, TId u "s", TEOF u]++ resetSrcSpan (collectFixedTokens' Fortran77Legacy " character s*(*)")+ `shouldBe` resetSrcSpan [TType u "character", TId u "s", TStar u, TLeftPar u, TStar u, TRightPar u, TEOF u]++ it "lexes strings case-sensitively" $+ resetSrcSpan (collectFixedTokens' Fortran77Legacy " c = 'Hello'")+ `shouldBe` resetSrcSpan [TId u "c", TOpAssign u, TString u "Hello", TEOF u]++ it "lexes strings delimited by '\"'" $+ resetSrcSpan (collectFixedTokens' Fortran77Legacy " c = \"hello\"")+ `shouldBe` resetSrcSpan [TId u "c", TOpAssign u, TString u "hello", TEOF u]++ it "lexes Hollerith constants" $ do+ resetSrcSpan (collectFixedTokens' Fortran77Legacy " x = 7hmistral")+ `shouldBe` resetSrcSpan [TId u "x", TOpAssign u, THollerith u "mistral", TEOF u]++ resetSrcSpan (collectFixedTokens' Fortran77Legacy " x = 7hshort\n")+ `shouldBe` resetSrcSpan [TId u "x", TOpAssign u, THollerith u "short ", TNewline u, TEOF u]++ it "lexes BOZ constants" $+ resetSrcSpan (collectFixedTokens' Fortran77Legacy " integer i, j, k / b'0101', o'0755', z'ab01' /")+ `shouldBe` resetSrcSpan [ TType u "integer"+ , TId u "i", TComma u, TId u "j", TComma u, TId u "k"+ , TSlash u, TBozLiteral u (parseBoz "b'0101'")+ , TComma u, TBozLiteral u (parseBoz "o'0755'")+ , TComma u, TBozLiteral u (parseBoz "z'ab01'")+ , TSlash u , TEOF u ]++ it "lexes non-standard identifiers" $+ resetSrcSpan (collectFixedTokens' Fortran77Legacy " integer _this_is_a_long_identifier$")+ `shouldBe` resetSrcSpan [TType u "integer", TId u "_this_is_a_long_identifier$", TEOF u]++ it "lexes ';' as a line-terminator" $+ 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]++ it "lexes labeled DO WHILE blocks" $+ resetSrcSpan (collectFixedTokens' Fortran77Legacy " do 10 while (.true.)")+ `shouldBe` resetSrcSpan [TDo u, TInt u "10", TWhile u, TLeftPar u, TBool u True, TRightPar u, TEOF u]++ it "lexes structure/union/map blocks" $ do+ let src = unlines [ " structure /foo/"+ , " union"+ , " map"+ , " integer i"+ , " real r"+ , " end map"+ , " end union"+ , " end structure"]+ resetSrcSpan (collectFixedTokens' Fortran77Legacy src)+ `shouldBe` resetSrcSpan [ TStructure u, TSlash u, TId u "foo", TSlash u, TNewline u+ , TUnion u, TNewline u+ , TMap u, TNewline u+ , TType u "integer", TId u "i", TNewline u+ , TType u "real", TId u "r", TNewline u+ , TEndMap u, TNewline u+ , TEndUnion u, TNewline u+ , TEndStructure u, TNewline u+ , TEOF u ]++ it "lexes but skips comments after 72" $ do+ let src = unlines [ " l = r" <> replicate 65 ' ' <> "! comment after 72"+ , " r = l"+ , replicate 72 ' ' <> "blank line with comment"]+ resetSrcSpan (collectFixedTokens' Fortran77Legacy src) `shouldBe`+ resetSrcSpan [ TId u "l", TOpAssign u, TId u "r", TNewline u+ , TId u "r", TOpAssign u, TId u "l", TNewline u+ , TNewline u, TEOF u]+ it "lexes comment overflow" $ do+ let src = unlines+ [ " l = r" <> replicate 65 ' ' <> "Comment overflowing 72 limit"+ , " r = l"+ ]+ resetSrcSpan (collectFixedTokens' Fortran77Legacy src) `shouldBe`+ resetSrcSpan [ TId u "l", TOpAssign u, TId u "r", TNewline u+ , TId u "r", TOpAssign u, TId u "l", TNewline u, TEOF u]+ it "lexel comment line overflow" $ do+ let src = unlines [ replicate 80 'c'+ , " l = r" ]+ resetSrcSpan (collectFixedTokens' Fortran77Legacy src) `shouldBe`+ resetSrcSpan [ TComment u (replicate 71 'c'), TNewline u+ , TId u "l", TOpAssign u, TId u "r", TNewline u, TEOF u]++example1 :: String+example1 = unlines [+ " intEGerix",+ "1 iX= 42",+ " 200 ix =IX* ix",+ " 10 wrITe (*,*), ix",+ " EnD" ]++continuationExample :: String+continuationExample = unlines [+ " inte",+ " .ger i",+ " .x",+ " ix = 4",+ " .2",+ " end"]++example1Expectation :: [Token]+example1Expectation = [+ TType u "integer", TId u "ix", TNewline u,+ TLabel u "1", TId u "ix", TOpAssign u, TInt u "42", TNewline u,+ TLabel u "200", TId u "ix", TOpAssign u, TId u "ix", TStar u, TId u "ix", TNewline u,+ TLabel u "10", TWrite u, TLeftPar u, TStar u, TComma u, TStar u, TRightPar u, TComma u, TId u "ix", TNewline u,+ TEnd u, TNewline u,+ TEOF u]
− test/Language/Fortran/Parser/Fortran2003Spec.hs
@@ -1,180 +0,0 @@-module Language.Fortran.Parser.Fortran2003Spec where---import Prelude hiding (GT, EQ, exp, pred)--import Test.Hspec-import TestUtil-import Language.Fortran.Parser.FreeFormCommon--import Language.Fortran.AST-import Language.Fortran.ParserMonad-import Language.Fortran.Lexer.FreeForm-import Language.Fortran.Parser.Fortran2003-import qualified Data.ByteString.Char8 as B--eParser :: String -> Expression ()-eParser sourceCode =- case evalParse statementParser parseState of- (StExpressionAssign _ _ _ e) -> e- _ -> error "unhandled evalParse"- where- paddedSourceCode = B.pack $ " a = " ++ sourceCode- parseState = initParseState paddedSourceCode Fortran2003 "<unknown>"--simpleParser :: Parse AlexInput Token a -> String -> a-simpleParser p sourceCode =- evalParse p $ initParseState (B.pack sourceCode) Fortran2003 "<unknown>"--sParser :: String -> Statement ()-sParser = simpleParser statementParser--fParser :: String -> ProgramUnit ()-fParser = simpleParser functionParser--bParser :: String -> Block ()-bParser = simpleParser blockParser--spec :: Spec-spec =- describe "Fortran 2003 Parser" $ do- describe "Modules" $ do- it "parses use statement, intrinsic module" $ do- let renames = fromList ()- [ UseRename () u (varGen "sprod") (varGen "prod")- , UseRename () u (varGen "a") (varGen "b") ]- st = StUse () u (varGen "mod") (Just ModIntrinsic) Permissive (Just renames)- sParser "use, intrinsic :: mod, sprod => prod, a => b" `shouldBe'` st-- it "parses use statement, non_intrinsic module" $ do- let renames = fromList ()- [ UseRename () u (varGen "sprod") (varGen "prod")- , UseRename () u (varGen "a") (varGen "b") ]- st = StUse () u (varGen "mod") (Just ModNonIntrinsic) Exclusive (Just renames)- sParser "use, non_intrinsic :: mod, only: sprod => prod, a => b" `shouldBe'` st-- it "parses use statement, unspecified nature of module" $ do- let renames = fromList ()- [ UseRename () u (varGen "sprod") (varGen "prod")- , UseRename () u (varGen "a") (varGen "b") ]- st = StUse () u (varGen "mod") Nothing Permissive (Just renames)- sParser "use :: mod, sprod => prod, a => b" `shouldBe'` st-- it "parses procedure (interface-name, attribute, proc-decl)" $ do- let call = ExpFunctionCall () u (varGen "c") Nothing- st = StProcedure () u (Just (ProcInterfaceName () u (varGen "a")))- (Just (AttrSave () u))- (AList () u [ProcDecl () u (varGen "b") (Just call)])- sParser "PROCEDURE(a), SAVE :: b => c()" `shouldBe'` st-- it "parses procedure (class-star, bind-name, proc-decls)" $ do- let call = ExpFunctionCall () u (varGen "c") Nothing- clas = TypeSpec () u ClassStar Nothing- st = StProcedure () u (Just (ProcInterfaceType () u clas))- (Just (AttrSuffix () u (SfxBind () u (Just (ExpValue () u (ValString "e"))))))- (AList () u [ProcDecl () u (varGen "b") (Just call)- ,ProcDecl () u (varGen "d") (Just call)])- sParser "PROCEDURE(CLASS(*)), BIND(C, NAME=\"e\") :: b => c(), d => c()" `shouldBe'` st-- it "parses procedure (class-custom, bind, proc-decls)" $ do- let call = ExpFunctionCall () u (varGen "c") Nothing- clas = TypeSpec () u (ClassCustom "e") Nothing- st = StProcedure () u (Just (ProcInterfaceType () u clas))- (Just (AttrSuffix () u (SfxBind () u Nothing)))- (AList () u [ProcDecl () u (varGen "b") (Just call)- ,ProcDecl () u (varGen "d") (Just call)])- sParser "PROCEDURE(CLASS(e)), BIND(C) :: b => c(), d => c()" `shouldBe'` st-- it "import statements" $ do- let st = StImport () u (AList () u [varGen "a", varGen "b"])- sParser "import a, b" `shouldBe'` st- sParser "import :: a, b" `shouldBe'` st-- it "parses function with bind" $ do- let puFunction = PUFunction () u- fType = Nothing- fPre = emptyPrefixes- fSuf = fromList' () [SfxBind () u (Just $ ExpValue () u (ValString "f"))]- fName = "f"- fArgs = Nothing- fRes = Nothing- fBody = []- fSub = Nothing- fStr = init $ unlines ["function f() bind(c,name=\"f\")"- , "end function f" ]- let expected = puFunction fType (fPre, fSuf) fName fArgs fRes fBody fSub- fParser fStr `shouldBe'` expected-- it "parses asynchronous decl" $ do- let decls = [declVarGen "a", declVarGen "b"]- st = StAsynchronous () u (AList () u decls)- sParser "asynchronous a, b" `shouldBe'` st- sParser "asynchronous :: a, b" `shouldBe'` st-- it "parses asynchronous attribute" $ do- let decls = [declVarGen "a", declVarGen "b"]- ty = TypeSpec () u TypeInteger Nothing- attrs = [AttrAsynchronous () u]- st = StDeclaration () u ty (Just (AList () u attrs)) (AList () u decls)- sParser "integer, asynchronous :: a, b" `shouldBe'` st-- it "parses enumerators" $ do- let decls = [ declVariable () u (varGen "a") Nothing (Just (intGen 1))- , declVariable () u (varGen "b") Nothing Nothing ]- st = StEnumerator () u (AList () u decls)- sParser "enum, bind(c)" `shouldBe'` StEnum () u- sParser "enumerator :: a = 1, b" `shouldBe'` st- sParser "end enum" `shouldBe'` StEndEnum () u-- it "parses allocate with type_spec" $ do- let sel = Selector () u (Just (ExpValue () u ValColon)) (Just (varGen "foo"))- ty = TypeSpec () u TypeCharacter (Just sel)- decls = AList () u [declVarGen "s"]- st = StDeclaration () u ty (Just (AList () u [AttrAllocatable () u])) decls- sParser "character(len=:,kind=foo), allocatable :: s" `shouldBe'` st-- it "parses allocate with type_spec" $ do- let sel = Selector () u (Just (intGen 3)) (Just (varGen "foo"))- ty = TypeSpec () u TypeCharacter (Just sel)- st = StAllocate () u (Just ty) (AList () u [varGen "s"]) Nothing- sParser "allocate(character(len=3,kind=foo) :: s)" `shouldBe'` st-- it "parses protected" $ do- let ty = TypeSpec () u TypeReal Nothing- decls = AList () u [declVarGen "x"]- st1 = StDeclaration () u ty (Just (AList () u [AttrProtected () u, AttrPublic () u])) decls- st2 = StProtected () u (Just (AList () u [varGen "x"]))- sParser "real, protected, public :: x" `shouldBe'` st1- sParser "protected x" `shouldBe'` st2-- describe "labelled where" $ do- it "parses where construct statement" $- sParser "foo: where (.true.)" `shouldBe'` StWhereConstruct () u (Just "foo") valTrue-- it "parses elsewhere statement" $- sParser "elsewhere ab101" `shouldBe'` StElsewhere () u (Just "ab101") Nothing-- it "parses elsewhere statement" $ do- let exp = ExpBinary () u GT (varGen "a") (varGen "b")- sParser "elsewhere (a > b) A123" `shouldBe'` StElsewhere () u (Just "a123") (Just exp)-- it "parses endwhere statement" $- sParser "endwhere foo1" `shouldBe'` StEndWhere () u (Just "foo1")-- describe "associate block" $ do- it "parses multiple assignment associate block" $ do- let text = unlines [ "associate (x => a, y => (a * b))"- , " print *, x"- , " print *, y"- , "end associate" ]- expected = BlAssociate () u Nothing Nothing abbrevs body' Nothing- body' = [blStmtPrint "x", blStmtPrint "y"]- blStmtPrint x = BlStatement () u Nothing (stmtPrint x)- stmtPrint x = StPrint () u starVal (Just $ AList () u [ varGen x ])- abbrevs = AList () u [abbrev "x" (expValVar "a"), abbrev "y" (expBinVars Multiplication "a" "b")]- abbrev var expr = ATuple () u (expValVar var) expr- expValVar x = ExpValue () u (ValVariable x)- expBinVars op x1 x2 = ExpBinary () u op (expValVar x1) (expValVar x2)- bParser text `shouldBe'` expected-- specFreeFormCommon sParser eParser
− test/Language/Fortran/Parser/Fortran2008Spec.hs
@@ -1,8 +0,0 @@-module Language.Fortran.Parser.Fortran2008Spec where--import Test.Hspec--spec :: Spec-spec =- describe "Fortran 2008 Parser" $- it "TODO" pending
− test/Language/Fortran/Parser/Fortran66Spec.hs
@@ -1,190 +0,0 @@-module Language.Fortran.Parser.Fortran66Spec(spec) where--import Test.Hspec-import TestUtil--import Prelude hiding (LT)--import Language.Fortran.Parser.Fortran66-import Language.Fortran.Lexer.FixedForm-import Language.Fortran.ParserMonad-import Language.Fortran.AST-import qualified Data.ByteString.Char8 as B--eParser :: String -> Expression ()-eParser sourceCode =- case evalParse statementParser parseState of- (StExpressionAssign _ _ _ e) -> e- _ -> error "unhandled evalParse"- where- paddedSourceCode = B.pack $ " a = " ++ sourceCode- parseState = initParseState paddedSourceCode Fortran66 "<unknown>"--sParser :: String -> Statement ()-sParser sourceCode =- evalParse statementParser $ initParseState (B.pack sourceCode) Fortran66 "<unknown>"--spec :: Spec-spec =- describe "Fortran 66 Parser" $ do- describe "Expressions" $ do- describe "Arithmetic expressions" $ do- it "parses '3'" $ do- let expectedExp = intGen 3- eParser "3" `shouldBe'` expectedExp-- it "parses '-3'" $ do- let expectedExp = ExpUnary () u Minus $ intGen 3- eParser "-3" `shouldBe'` expectedExp-- it "parses '3 + 2'" $ do- let expectedExp = ExpBinary () u Addition (intGen 3) (intGen 2)- eParser "3 + 2" `shouldBe'` expectedExp-- it "parses '3 + -2'" $ do- let expectedExp = ExpBinary () u Addition (intGen 3) (ExpUnary () u Minus (intGen 2))- eParser "3 + -2" `shouldBe'` expectedExp-- it "parses '3 + -2 + 42'" $ do- let expectedExp = ExpBinary () u Addition (ExpBinary () u Addition (intGen 3) (ExpUnary () u Minus (intGen 2))) (intGen 42)- eParser "3 + -2 + 42" `shouldBe'` expectedExp-- it "parses 'f(y, 24)'" $ do- let subs = [ IxSingle () u Nothing $ varGen "y", ixSinGen 24 ]- let expectedExp = ExpSubscript () u (varGen "f") (fromList () subs)- eParser "f(y, 24)" `shouldBe'` expectedExp-- it "parses '3 + 4 * 12'" $ do- let expectedExp = ExpBinary () u Addition (intGen 3) (ExpBinary () u Multiplication (intGen 4) (intGen 12))- eParser "3 + 4 * 12" `shouldBe'` expectedExp-- describe "Logical expressions" $- it "parses '.true. .and. .false.'" $ do- let expectedExp = ExpBinary () u And valTrue valFalse- eParser ".true. .and. .false." `shouldBe'` expectedExp-- describe "Relational expressions" $- it "parses '(3 * 2) .lt. 42'" $ do- let expectedExp = ExpBinary () u LT (ExpBinary () u Multiplication (intGen 3) (intGen 2)) (intGen 42)- eParser "(3 * 2) .lt. 42" `shouldBe'` expectedExp-- describe "Other expressions" $- it "parses 'a(2 * x - 3, 10)'" $ do- let firstEl = ExpBinary () u Subtraction (ExpBinary () u Multiplication (intGen 2) (varGen "x")) (intGen 3)- expectedExp = ExpSubscript () u (varGen "a") (AList () u [ IxSingle () u Nothing firstEl, ixSinGen 10])- eParser "a(2 * x - 3, 10)" `shouldBe'` expectedExp-- describe "Statements" $ do- it "parses 'EXTERNAL f, g, h'" $ do- let procGen s = ExpValue () u (ValVariable s)- let expectedSt = StExternal () u (AList () u [procGen "f", procGen "g", procGen "h"])- sParser " EXTERNAL f, g, h" `shouldBe'` expectedSt-- it "parses 'COMMON a, b'" $ do- let comGr = CommonGroup () u Nothing (AList () u [ declVarGen "a", declVarGen "b" ])- let st = StCommon () u (AList () u [ comGr ])- sParser " COMMON a, b" `shouldBe'` st-- it "parses 'COMMON // a, b /hello/ x, y, z'" $ do- let comGrs = [ CommonGroup () u Nothing (AList () u [ declVarGen "a", declVarGen "b" ])- , CommonGroup () u (Just $ varGen "hello") (AList () u [ declVarGen "x", declVarGen "y", declVarGen "z" ]) ]- let st = StCommon () u (AList () u comGrs)- sParser " COMMON // a, b /hello/ x, y, z" `shouldBe'` st-- it "parses 'EQUIVALENCE (a,b), (x,y,z)'" $ do- let ls = [ AList () u [varGen "a", varGen "b"]- , AList () u [varGen "x", varGen "y", varGen "z"] ]- let st = StEquivalence () u (AList () u ls)- sParser " EQUIVALENCE (a,b), (x,y,z)" `shouldBe'` st-- it "parses 'DATA a/1,2,3/,x/42/'" $ do- let dGrs = [ DataGroup () u (AList () u [varGen "a"]) (AList () u [intGen 1, intGen 2, intGen 3])- , DataGroup () u (AList () u [varGen "x"]) (AList () u [intGen 42]) ]- let st = StData () u $ AList () u dGrs- sParser " DATA a/1,2,3/, x/42/" `shouldBe'` st-- describe "FORMAT" $ do- it "parses 'FORMAT ()'" $ do- let expectedSt = StFormatBogus () u "()"- sParser " FORMAT ()" `shouldBe'` expectedSt-- it "parses 'FORMAT (///)'" $ do- let expectedSt = StFormatBogus () u "(///)"- sParser " FORMAT (///)" `shouldBe'` expectedSt-- it "parses 'FORMAT (2i5/5hhello)'" $ do- let expectedSt = StFormatBogus () u "(2i5/5hhello)"- sParser " FORMAT (2i5/5hhello)" `shouldBe'` expectedSt-- it "parses 'FORMAT (/(i5))'" $ do- let expectedSt = StFormatBogus () u "(/(i5))"- sParser " FORMAT (/(i5))" `shouldBe'` expectedSt-- describe "CALL" $ do- it "parses 'CALL me" $ do- let expectedSt = StCall () u (ExpValue () u (ValVariable "me")) Nothing- sParser " CALL me" `shouldBe'` expectedSt-- it "parses 'CALL me(baby)" $ do- let args = AList () u [ Argument () u Nothing $ varGen "baby" ]- let expectedSt = StCall () u (ExpValue () u (ValVariable "me")) $ Just args- sParser " CALL me(baby)" `shouldBe'` expectedSt-- it "parses 'stop'" $ do- let expectedSt = StStop () u Nothing- sParser " stop" `shouldBe'` expectedSt-- it "parses 'integer i, j(2,2), k'" $ do- let dimDecls = replicate 2 $ DimensionDeclarator () u Nothing (Just $ intGen 2)- declarators = [ Declarator () u (varGen "i") ScalarDecl Nothing Nothing- , Declarator () u (varGen "j") (ArrayDecl (AList () u dimDecls)) Nothing Nothing- , Declarator () u (varGen "k") ScalarDecl Nothing Nothing ]- st = StDeclaration () u (TypeSpec () u TypeInteger Nothing) Nothing $ AList () u declarators- sParser " integer i, j(2,2), k" `shouldBe'` st-- let controlPairs = AList () u [ ControlPair () u Nothing (intGen 6), ControlPair () u Nothing (labelGen 10) ]- let writeSt = StWrite () u controlPairs (Just $ AList () u [ varGen "i" ])-- describe "WRITE" $ do- it "parses 'write (6)'" $ do- let expectedSt = StWrite () u (AList () u [ ControlPair () u Nothing (intGen 6) ]) Nothing- sParser " write (6)" `shouldBe'` expectedSt-- it "parses 'write (6) i'" $ do- let expectedSt = StWrite () u (AList () u [ ControlPair () u Nothing (intGen 6) ]) (Just $ AList () u [ varGen "i" ])- sParser " write (6) i" `shouldBe'` expectedSt-- it "parses 'write (6,10) i'" $- sParser " write (6,10) i" `shouldBe'` writeSt-- describe "IF" $ do- it "parses 'if (10 .LT. x) write (6,10) i'" $ do- let cond = ExpBinary () u LT (intGen 10) (varGen "x")- let expectedSt = StIfLogical () u cond writeSt- sParser " if (10 .LT. x) write (6,10) i" `shouldBe'` expectedSt-- it "parses 'if (10 - 5) 10, 20, 30'" $ do- let cond = ExpBinary () u Subtraction (intGen 10) (intGen 5)- let expectedSt = StIfArithmetic () u cond (labelGen 10) (labelGen 20) (labelGen 30)- sParser " if (10 - 5) 10, 20, 30" `shouldBe'` expectedSt-- it "parses 'IF (IY) 5,6,6" $ do- let expectedSt = StIfArithmetic () u (varGen "iy") (labelGen 5) (labelGen 6) (labelGen 6)- sParser " IF (IY) 5,6,6" `shouldBe'` expectedSt-- describe "ASSIGNMENT" $ do- it "parses 'f = 1'" $ do- let expectedSt = StExpressionAssign () u (varGen "f") (intGen 1)- sParser " f = 1" `shouldBe'` expectedSt-- it "parses 'f = a(1,2)'" $ do- let indicies = fromList () [ ixSinGen 1, ixSinGen 2 ]- let rhs = ExpSubscript () u (varGen "a") indicies- let expectedSt = StExpressionAssign () u (varGen "f") rhs- sParser " f = a(1,2)" `shouldBe'` expectedSt-- it "parses 'do 42 i = 10, 1, 1'" $ do- let st = StExpressionAssign () u (varGen "i") (intGen 10)- let doSpec = DoSpecification () u st (intGen 1) (Just $ intGen 1)- let expectedSt = StDo () u Nothing (Just $ labelGen 42) (Just doSpec)- sParser " do 42 i = 10, 1, 1" `shouldBe'` expectedSt
− test/Language/Fortran/Parser/Fortran77/IncludeSpec.hs
@@ -1,55 +0,0 @@-module Language.Fortran.Parser.Fortran77.IncludeSpec where--import System.FilePath-import Test.Hspec-import TestUtil--import Language.Fortran.Parser.Fortran77-import qualified Data.ByteString.Char8 as B-import Language.Fortran.ParserMonad-import Language.Fortran.Lexer.FixedForm-import Language.Fortran.AST-import Language.Fortran.Util.Position--iParser :: [String] -> String -> IO (ParseResult AlexInput Token (ProgramFile A0))-iParser incs src = legacy77ParserWithIncludes incs (B.pack src) "<unknown>"--makeSrcR :: (Int, Int, Int, String) -> (Int, Int, Int, String) -> SrcSpan-makeSrcR (i1, i2, i3, s) (j1, j2, j3, s') = SrcSpan (Position i1 i2 i3 s Nothing) (Position j1 j2 j3 s' Nothing)--spec :: SpecWith ()-spec =- describe "Include Test" $ do- let source = unlines [" program bar",- " include 'foo.f'",- " end"- ]- inc = "./test-data/f77-include"- name = "bar"- pf = ProgramFile mi77 [pu]- puSpan = makeSrcR (6,7,1,"<unknown>") (48,9,3,"<unknown>")- st1Span = makeSrcR (24,7,2,"<unknown>") (38,21,2,"<unknown>")- expSpan = makeSrcR (32,15,2,"<unknown>") (38,21,2,"<unknown>")-- -- the expansion returns the span in the included file- -- it should return the span at the inclusion- foo = inc </> "foo.f"- st2Span = makeSrcR (6,7,1, foo) (14,15,1,foo)- declSpan = makeSrcR (6,7,1,foo) (14,15,1,foo)- typeSpan = makeSrcR (6,7,1,foo) (12,13,1,foo)- blockSpan = makeSrcR (14,15,1,foo) (14,15,1,foo)- varGen' str = ExpValue () blockSpan $ ValVariable str-- pu = PUMain () puSpan (Just name) blocks Nothing- blocks = [bl1]- decl = Declarator () blockSpan (varGen' "a") ScalarDecl Nothing Nothing- typeSpec = TypeSpec () typeSpan TypeInteger Nothing- st2 = StDeclaration () st2Span typeSpec Nothing (AList () blockSpan [decl])- bl1 = BlStatement () st1Span Nothing st1- st1 = StInclude () st1Span ex (Just [bl2])- ex = ExpValue () expSpan (ValString "foo.f")- bl2 = BlStatement () declSpan Nothing st2- it "includes some files and expands them" $ do- ps <- iParser [inc] source- let pr = fromParseResultUnsafe ps- pr `shouldBe` pf
− test/Language/Fortran/Parser/Fortran77/ParserSpec.hs
@@ -1,424 +0,0 @@-module Language.Fortran.Parser.Fortran77.ParserSpec where--import Test.Hspec-import TestUtil--import Prelude hiding (exp)-import Language.Fortran.Parser.Fortran77-import Language.Fortran.Lexer.FixedForm (initParseState)-import Language.Fortran.ParserMonad (FortranVersion(..), evalParse, fromParseResultUnsafe)-import Language.Fortran.AST-import qualified Data.ByteString.Char8 as B--{-# ANN module "HLint: ignore Reduce duplication" #-}--eParser :: String -> Expression ()-eParser sourceCode =- case evalParse statementParser parseState of- (StExpressionAssign _ _ _ e) -> e- _ -> error "unhandled evalParse"- where- paddedSourceCode = B.pack $ " a = " ++ sourceCode- parseState = initParseState paddedSourceCode Fortran77 "<unknown>"--sParser :: String -> Statement ()-sParser sourceCode =- evalParse statementParser $ initParseState (B.pack sourceCode) Fortran77 "<unknown>"--slParser :: String -> Statement ()-slParser sourceCode =- evalParse statementParser $ initParseState (B.pack sourceCode) Fortran77Legacy "<unknown>"--blParser :: String -> Block ()-blParser src = evalParse blockParser $ initParseState (B.pack src) Fortran77Legacy "<unknown>"--iParser :: String -> [Block ()]-iParser sourceCode =- fromParseResultUnsafe $ includeParser Fortran77Legacy (B.pack sourceCode) "<unknown>"--pParser :: String -> ProgramFile ()-pParser source = fromParseResultUnsafe $ legacy77Parser (B.pack source) "<unknown>"--spec :: Spec-spec =- describe "Fortran 77 Parser" $ do- describe "IO" $ do- it "parses 'print *, 9000" $ do- let expectedSt = StPrint () u starVal $ Just (AList () u [ intGen 9000 ])- sParser " print *, 9000" `shouldBe'` expectedSt-- it "parses 'write (UNIT=6, FORMAT=*)" $ do- let cp1 = ControlPair () u (Just "unit") (intGen 6)- cp2 = ControlPair () u (Just "format") starVal- expectedSt = StWrite () u (AList () u [cp1, cp2]) Nothing- sParser " write (UNIT=6, FORMAT=*)" `shouldBe'` expectedSt-- it "parses 'endfile i" $- sParser " endfile i" `shouldBe'` StEndfile2 () u (varGen "i")-- it "parses 'read *, (x, y(i), i = 1, 10, 2)'" $ do- let stAssign = StExpressionAssign () u (varGen "i") (intGen 1)- doSpec = DoSpecification () u stAssign (intGen 10) (Just $ intGen 2)- impliedDoVars = AList () u [ varGen "x", ExpSubscript () u (varGen "y") (AList () u [ IxSingle () u Nothing $ varGen "i" ])]- impliedDo = ExpImpliedDo () u impliedDoVars doSpec- iolist = AList () u [ impliedDo ]- expectedSt = StRead2 () u starVal (Just iolist)- sParser " read *, (x, y(i), i = 1, 10, 2)" `shouldBe'` expectedSt-- it "parses '(x, y(i), i = 1, 10, 2)'" $ do- let stAssign = StExpressionAssign () u (varGen "i") (intGen 1)- doSpec = DoSpecification () u stAssign (intGen 10) (Just $ intGen 2)- impliedDoVars = AList () u [ varGen "x", ExpSubscript () u (varGen "y") (AList () u [ IxSingle () u Nothing $ varGen "i" ])]- impliedDo = ExpImpliedDo () u impliedDoVars doSpec- eParser "(x, y(i), i = 1, 10, 2)" `shouldBe'` impliedDo-- it "parses main program unit" $ do- let decl = declVarGen "x"- st = StDeclaration () u (TypeSpec () u TypeInteger Nothing) Nothing (AList () u [ decl ])- bl = BlStatement () u Nothing st- pu = ProgramFile mi77 [ PUMain () u (Just "hello") [ bl ] Nothing ]- pParser exampleProgram1 `shouldBe'` pu-- it "parses block data unit" $ do- let decl = declVarGen "x"- st = StDeclaration () u (TypeSpec () u TypeInteger Nothing) Nothing (AList () u [ decl ])- bl = BlStatement () u Nothing st- pu = ProgramFile mi77 [ PUBlockData () u (Just "hello") [ bl ] ]- pParser exampleProgram2 `shouldBe'` pu-- it "parses 'intrinsic cosh, sin'" $ do- let st = StIntrinsic () u (AList () u [ varGen "cosh", varGen "sin" ])- sParser " intrinsic cosh, sin" `shouldBe'` st-- it "parses 'intrinsic real" $ do- let st = StIntrinsic () u (AList () u [ varGen "real" ])- sParser " intrinsic real" `shouldBe'` st-- describe "CHARACTER" $ do- it "parses character literal assignment" $ do- let rhs = ExpValue () u (ValString "hello 'baby")- st = StExpressionAssign () u (varGen "xyz") rhs- sParser " xyz = 'hello ''baby'" `shouldBe'` st-- it "string concatenation" $ do- let str1 = ExpValue () u (ValString "hello ")- str2 = ExpValue () u (ValString "world")- exp = ExpBinary () u Concatenation str1 str2- eParser "'hello ' // 'world'" `shouldBe'` exp-- describe "Subscript like" $ do- it "parses vanilla subscript" $ do- let exp = ExpSubscript () u (varGen "a") (AList () u [ IxSingle () u Nothing $ varGen "x", IxSingle () u Nothing $ intGen 2, IxSingle () u Nothing $ intGen 3 ])- eParser "a(x, 2, 3)" `shouldBe'` exp-- it "parses array declarator" $ do- let dimDecls = [ DimensionDeclarator () u (Just $ intGen 1) (Just $ intGen 2)- , DimensionDeclarator () u Nothing (Just $ intGen 15)- , DimensionDeclarator () u (Just $ varGen "x") (Just starVal) ]- decl = declArray () u (varGen "a") (AList () u dimDecls) Nothing Nothing- st = StDeclaration () u (TypeSpec () u TypeInteger Nothing) Nothing (AList () u [ decl ])- sParser " integer a(1:2, 15, x:*)" `shouldBe'` st-- it "parses character substring" $ do- let indicies = [ ixSinGen 1, ixSinGen 2, ixSinGen 3 ]- subExp = ExpSubscript () u (varGen "a") (AList () u indicies)- range = IxRange () u Nothing (Just $ intGen 10) Nothing- exp = ExpSubscript () u subExp (AList () u [ range ])- eParser "a(1, 2, 3)(:10)" `shouldBe'` exp-- it "parses simpler substring" $ do- let exp = ExpSubscript () u (varGen "a") (AList () u [ ixRanGen 5 10 ])- eParser "a(5:10)" `shouldBe'` exp-- it "parses simpler substring" $ do- let range = IxRange () u (Just $ intGen 5) Nothing Nothing- exp = ExpSubscript () u (varGen "a") (AList () u [ range ])- eParser "a(5:)" `shouldBe'` exp-- it "parses literal string subscript" $ do- let range = IxRange () u (Just $ intGen 1) (Just $ intGen 2) Nothing- exp = ExpSubscript () u (strGen "abc") (AList () u [ range ])- eParser "'abc'(1:2)" `shouldBe'` exp-- describe "GOTO" $ do- it "parses computed GOTO with integer expression" $ do- let exp = ExpBinary () u Multiplication (intGen 42) (intGen 24)- st = StGotoComputed () u (AList () u [labelGen 10, labelGen 20, labelGen 30]) exp- sParser " GOTO (10, 20, 30), 42 * 24" `shouldBe'` st-- let gotoSt = StGotoAssigned () u (varGen "v") (Just (AList () u [labelGen 10, labelGen 20, labelGen 30]))- it "parses assigned GOTO with comma" $- sParser " GOTO v, (10, 20, 30)" `shouldBe'` gotoSt-- it "parses assigned GOTO without comma" $- sParser " GOTO v (10, 20, 30)" `shouldBe'` gotoSt-- describe "IMPLICIT" $ do- it "parses 'implicit none'" $ do- let st = resetSrcSpan $ StImplicit () u Nothing- sParser " implicit none" `shouldBe'` st-- it "parses 'implicit character*30 (a, b, c), integer (a-z, l)" $ do- let impEls = [ImpCharacter () u "a", ImpCharacter () u "b", ImpCharacter () u "c"]- sel = Selector () u (Just (intGen 30)) Nothing- imp1 = ImpList () u (TypeSpec () u TypeCharacter (Just sel)) $ AList () u impEls- imp2 = ImpList () u (TypeSpec () u TypeInteger Nothing) $ AList () u [ImpRange () u "a" "z", ImpCharacter () u "l"]- st = StImplicit () u $ Just $ AList () u [imp1, imp2]- sParser " implicit character*30 (a, b, c), integer (a-z, l)" `shouldBe'` st-- it "parses 'parameter (pi = 3.14, b = 'X' // 'O', d = k) '" $ do- let sts = [ declVariable () u (varGen "pi") Nothing (Just $ realGen (3.14::Double))- , let e = ExpBinary () u Concatenation (strGen "X") (strGen "O")- in declVariable () u (varGen "b") Nothing (Just e)- , declVariable () u (varGen "d") Nothing (Just $ varGen "k") ]- st = StParameter () u (AList () u sts)- sParser " parameter (pi = 3.14, b = 'X' // 'O', d = k)" `shouldBe'` st-- it "parses 'pause 'hello world''" $ do- let st = StPause () u $ Just $ strGen "hello world"- sParser " pause 'hello world'" `shouldBe'` st-- describe "SAVE" $ do- it "parses 'save /cb/, var, /key/'" $ do- let saveArgs = [ varGen "cb", varGen "var", varGen "key" ]- st = StSave () u (Just $ AList () u saveArgs)- sParser " save /cb/, var, /key/" `shouldBe'` st-- it "parses 'save'" $- sParser " save" `shouldBe'` StSave () u Nothing-- it "parses '.true. .eqv. f(42) .neqv. x'" $ do- let arg2 = ExpSubscript () u (varGen "f") $ AList () u [ ixSinGen 42 ]- arg3 = varGen "x"- subexp = ExpBinary () u Equivalent valTrue arg2- exp = ExpBinary () u NotEquivalent subexp arg3- eParser ".true. .eqv. f(42) .neqv. x" `shouldBe'` exp-- it "parses 'entry me (a,b,*)'" $ do- let args = [ varGen "a", varGen "b", starVal ]- st = StEntry () u (varGen "me") (Just $ AList () u args) Nothing- sParser " entry me (a,b,*)" `shouldBe'` st-- it "parses 'character a*8'" $ do- let decl = declVariable () u (varGen "a") (Just $ intGen 8) Nothing- typeSpec = TypeSpec () u TypeCharacter Nothing- st = StDeclaration () u typeSpec Nothing (AList () u [ decl ])- sParser " character a*8" `shouldBe'` st-- it "parses 'character c*(ichar('A'))" $ do- let args = AList () u [ IxSingle () u Nothing (ExpValue () u (ValString "A")) ]- lenExpr = ExpSubscript () u (varGen "ichar") args- decl = declVariable () u (varGen "c") (Just $ lenExpr) Nothing- typeSpec = TypeSpec () u TypeCharacter Nothing- st = StDeclaration () u typeSpec Nothing (AList () u [ decl ])- sParser " character c*(ichar('A'))" `shouldBe'` st-- it "parses included files" $ do- let decl = declVariable () u (varGen "a") Nothing Nothing- typeSpec = TypeSpec () u TypeInteger Nothing- st = StDeclaration () u typeSpec Nothing (AList () u [ decl ])- bl = BlStatement () u Nothing st- iParser " integer a" `shouldBe'` [bl]-- describe "parses if blocks" $ do- let printArgs = Just $ AList () u [ExpValue () u $ ValString "foo"]- printStmt = StPrint () u (ExpValue () u ValStar) printArgs- printBlock = BlStatement () u Nothing printStmt- it "unlabelled" $ do- let bl = BlIf () u Nothing Nothing [ Just valTrue, Nothing ] [[printBlock], [printBlock]] Nothing- src = unlines [ " if (.true.) then ! comment if"- , " print *, 'foo'"- , " else ! comment else"- , " print *, 'foo'"- , " endif ! comment end"- ]- blParser src `shouldBe'` bl- it "labelled" $ do- let label = Just . intGen- bl = BlIf () u (label 10) Nothing [Just valTrue, Nothing] [[printBlock], [printBlock]] (label 30)- src = unlines [ "10 if (.true.) then ! comment if"- , " print *, 'foo'"- , "20 else ! comment else"- , " print *, 'foo'"- , "30 endif ! comment end"- ]- blParser src `shouldBe'` bl-- describe "Legacy Extensions" $ do- it "parses structure/union/map blocks" $ do- let src = init- $ unlines [ " structure /foo/"- , " union"- , " map"- , " integer i"- , " end map"- , " map"- , " real r"- , " end map"- , " end union"- , " end structure"]- ds = [ UnionMap () u $ AList () u- [StructFields () u (TypeSpec () u TypeInteger Nothing) Nothing $- AList () u [declVariable () u (varGen "i") Nothing Nothing]]- , UnionMap () u $ AList () u- [StructFields () u (TypeSpec () u TypeReal Nothing) Nothing $- AList () u [declVariable () u (varGen "r") Nothing Nothing]]- ]- st = StStructure () u (Just "foo") $ AList () u [StructUnion () u $ AList () u ds]- resetSrcSpan (slParser src) `shouldBe` st-- it "parses structure/union/map blocks with comments" $ do- let src = init- $ unlines [ " structure /foo/"- , "C comment before union"- , " union"- , "C comment inside union, before map"- , " map"- , "C comment inside map"- , " integer i ! more comment"- , " end map"- , "C comment between maps"- , " map"- , " real r ! more comment"- , " end map"- , "C comment after map"- , " end union"- , "C comment after union"- , " end structure"]- ds = [ UnionMap () u $ AList () u- [StructFields () u (TypeSpec () u TypeInteger Nothing) Nothing $- AList () u [declVariable () u (varGen "i") Nothing Nothing]]- , UnionMap () u $ AList () u- [StructFields () u (TypeSpec () u TypeReal Nothing) Nothing $- AList () u [declVariable () u (varGen "r") Nothing Nothing]]- ]- st = StStructure () u (Just "foo") $ AList () u [StructUnion () u $ AList () u ds]- resetSrcSpan (slParser src) `shouldBe` st-- it "parses nested structure blocks" $ do- let src = init- $ unlines [ " structure /foo/"- , " structure /bar/ baz"- , " integer qux"- , " end structure"- , " end structure"]- var = declVariable () u (varGen "qux") Nothing Nothing- innerst = StructStructure () u (Just "bar") ("baz")- $ AList () u [StructFields () u (TypeSpec () u TypeInteger Nothing) Nothing- $ AList () u [var]]- 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 (varGen "foo") (varGen "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- ext = blStmt $ StExternal () u $ AList () u [varGen "bar"]- arg = Just . AList () u . pure . Argument () u Nothing- valBar = ExpFunctionCall () u (ExpValue () u (ValIntrinsic "%val"))- $ arg $ varGen "baz"- call = blStmt $ StCall () u (varGen "bar") $ arg valBar- pu = ProgramFile mi77 [ PUSubroutine () u (Nothing, Nothing) "foo"- (Just $ AList () u [varGen "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 $- AList () u [declVariable () u- (varGen "s")- (Just (ExpValue () u ValStar))- Nothing]- resetSrcSpan (slParser src) `shouldBe` st-- it "parses array initializers" $ do- let src = " integer xs(3) / 1, 2, 3 /"- inits = [intGen 1, intGen 2, intGen 3]- st = StDeclaration () u (TypeSpec () u TypeInteger Nothing) Nothing $- AList () u [declArray () u- (varGen "xs")- (AList () u [DimensionDeclarator () u Nothing (Just (intGen 3))])- Nothing- (Just (ExpInitialisation () u $ AList () u inits))]- resetSrcSpan (slParser src) `shouldBe` st-- let src1 = " character xs(2)*5 / 'hello', 'world' /"- inits1 = [ExpValue () u (ValString "hello"), ExpValue () u (ValString "world")]- st1 = StDeclaration () u (TypeSpec () u TypeCharacter Nothing) Nothing $- AList () u [declArray () u- (varGen "xs")- (AList () u [DimensionDeclarator () u Nothing (Just (intGen 2))])- (Just (intGen 5))- (Just (ExpInitialisation () u $ AList () u inits1))]- resetSrcSpan (slParser src1) `shouldBe` st1-- let src2 = " character xs*5(2) / 'hello', 'world' /"- inits2 = [ExpValue () u (ValString "hello"), ExpValue () u (ValString "world")]- st2 = StDeclaration () u (TypeSpec () u TypeCharacter Nothing) Nothing $- AList () u [declArray () u- (varGen "xs")- (AList () u [DimensionDeclarator () u Nothing (Just (intGen 2))])- (Just (intGen 5))- (Just (ExpInitialisation () u $ AList () u inits2))]- resetSrcSpan (slParser src2) `shouldBe` st2-- it "parses subscripts in assignments" $ do- let mkIdx i = IxSingle () u Nothing (intGen i)-- src = " x(0,1) = 0"- tgt = ExpSubscript () u (varGen "x") (AList () u [mkIdx 0, mkIdx 1])- st = StExpressionAssign () u tgt (intGen 0)- resetSrcSpan (slParser src) `shouldBe` st-- let src1 = " x(0).foo = 0"- tgt1 = ExpDataRef () u (ExpSubscript () u (varGen "x") (AList () u [mkIdx 0])) (varGen "foo")- st1 = StExpressionAssign () u tgt1 (intGen 0)- resetSrcSpan (slParser src1) `shouldBe` st1-- let src2 = " x.foo = 0"- tgt2 = ExpDataRef () u (varGen "x") (varGen "foo")- st2 = StExpressionAssign () u tgt2 (intGen 0)- resetSrcSpan (slParser src2) `shouldBe` st2-- let src3 = " x.foo(0) = 0"- tgt3 = ExpSubscript () u (ExpDataRef () u (varGen "x") (varGen "foo")) (AList () u [mkIdx 0])- st3 = StExpressionAssign () u tgt3 (intGen 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- [ " program hello"- , " integer x"- , " end" ]--exampleProgram2 :: String-exampleProgram2 = unlines- [ " 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--- haskell-program-name: "cabal repl test-suite:spec"--- End:
− test/Language/Fortran/Parser/Fortran90Spec.hs
@@ -1,590 +0,0 @@-module Language.Fortran.Parser.Fortran90Spec (spec) where--import Prelude hiding (GT, exp, pred)--import Test.Hspec-import TestUtil-import Language.Fortran.Parser.FreeFormCommon--import Language.Fortran.AST-import Language.Fortran.ParserMonad-import Language.Fortran.Lexer.FreeForm-import Language.Fortran.Parser.Fortran90---import qualified Data.List as List-import qualified Data.ByteString.Char8 as B--{-# ANN module "HLint: ignore Reduce duplication" #-}--eParser :: String -> Expression ()-eParser sourceCode =- case evalParse statementParser parseState of- (StExpressionAssign _ _ _ e) -> e- _ -> error "unhandled evalParse"- where- paddedSourceCode = B.pack $ " a = " ++ sourceCode- parseState = initParseState paddedSourceCode Fortran90 "<unknown>"--sParser :: String -> Statement ()-sParser sourceCode =- evalParse statementParser $ initParseState (B.pack sourceCode) Fortran90 "<unknown>"--blParser :: String -> Block ()-blParser sourceCode =- evalParse blockParser $ initParseState (B.pack sourceCode) Fortran90 "<unknown>"--fParser :: String -> ProgramUnit ()-fParser sourceCode =- evalParse functionParser $ initParseState (B.pack sourceCode) Fortran95 "<unknown>"--{- Useful for parser debugging; Lexes the given source code.-fTok :: String -> [Token]-fTok sourceCode = collectFreeTokens Fortran95 $ B.pack sourceCode--}--{-- - Given a list of values, find every combination of those values:- - combination [1,2] = [[], [1], [2], [1,2], [2,1]]- -}---combination :: [a] -> [[a]]---combination = foldr ((++) . List.permutations) [] . List.subsequences--spec :: Spec-spec =- describe "Fortran 90 Parser" $ do- describe "Function" $ do- let puFunction = PUFunction () u- fType = Nothing- fPre = emptyPrefixes- fPreR = Just $ AList () u [PfxRecursive () u]- fSuf = emptySuffixes- fPreSuf = (fPre, fSuf)- fName = "f"- fArgs = Nothing- fRes = Nothing- fBody = []- fSub = Nothing-- describe "End" $ do- it "parses simple functions ending with \"end function [function name]\"" $ do- let expected = puFunction fType fPreSuf fName fArgs fRes fBody fSub- fStr = init $ unlines ["function f()"- , "end function f" ]- fParser fStr `shouldBe'` expected-- it "parses simple functions ending with \"end\"" $ do- let expected = puFunction fType fPreSuf fName fArgs fRes fBody fSub- fStr = init $ unlines ["function f()"- , "end" ]- fParser fStr `shouldBe'` expected-- it "parses simple functions ending with \"end function\"" $ do- let expected = puFunction fType fPreSuf fName fArgs fRes fBody fSub- fStr = init $ unlines ["function f()"- , "end function" ]- fParser fStr `shouldBe'` expected--- it "parses functions with return type specs" $ do- let fType' = Just $ TypeSpec () u TypeInteger Nothing- expected = puFunction fType' fPreSuf fName fArgs fRes fBody fSub- fStr = init $ unlines ["integer function f()"- , "end function f" ]- fParser fStr `shouldBe'` expected-- it "parses recursive functions" $- let expected = puFunction fType (fPreR, fSuf) fName fArgs fRes fBody fSub- fStr = init $ unlines ["recursive function f()", "end"]- in fParser fStr `shouldBe'` expected--- it "parses functions with a list of arguments" $- let fArgs' = Just $ AList () u [ varGen "x", varGen "y", varGen "z" ]- expected = puFunction fType fPreSuf fName fArgs' fRes fBody fSub- fStr = init $ unlines ["function f(x, y, z)"- , "end function f" ]- in fParser fStr `shouldBe'` expected-- it "parses functions with a result variable" $- let fRes' = Just $ varGen "i"- expected = puFunction fType fPreSuf fName fArgs fRes' fBody fSub- fStr = init $ unlines ["function f() result(i)"- , "end function f" ]- in fParser fStr `shouldBe'` expected-- it "parses functions with function bodies" $- let decrementRHS = ExpBinary () u Subtraction (varGen "i") (intGen 1)- f1 = StPrint () u starVal (Just $ AList () u [ varGen "i" ])- f2 = StExpressionAssign () u (varGen "i") decrementRHS- fBody' = [ BlStatement () u Nothing f1 , BlStatement () u Nothing f2 ]- expected = puFunction fType fPreSuf fName fArgs fRes fBody' fSub- fStr = init $ unlines ["function f()"- , " print *, i"- , " i = (i - 1)"- , "end function f" ]- in fParser fStr `shouldBe'` expected-- it "parses complex functions" $- let fType' = Just $ TypeSpec () u TypeInteger Nothing- fArgs' = Just $ AList () u [ varGen "x", varGen "y", varGen "z" ]- fRes' = Just $ varGen "i"- decrementRHS = ExpBinary () u Subtraction (varGen "i") (intGen 1)- f1 = StPrint () u starVal (Just $ AList () u [ varGen "i" ])- f2 = StExpressionAssign () u (varGen "i") decrementRHS- fBody' = [ BlStatement () u Nothing f1 , BlStatement () u Nothing f2 ]- expected = puFunction fType' fPreSuf fName fArgs' fRes' fBody' fSub- fStr = init $ unlines [ "integer function f(x, y, z) result(i)"- , " print *, i"- , " i = (i - 1)"- , "end function f" ]- in fParser fStr `shouldBe'` expected-- describe "Expression" $ do- it "parses logical literal without kind parameter" $ do- eParser ".true." `shouldBe'` valTrue-- it "parses logical literal with kind parameter" $ do- let kp = ExpValue () u (ValVariable "kind")- eParser ".false._kind" `shouldBe'` valFalse' kp-- it "parses array initialisation exp" $ do- let list = AList () u [ intGen 1, intGen 2, intGen 3, intGen 4 ]- eParser "(/ 1, 2, 3, 4 /)" `shouldBe'` ExpInitialisation () u list-- describe "Custom operator" $ do- let unOp = UnCustom ".inverse."- unExp = ExpUnary () u unOp $ intGen 42-- it "parses unary custom operator" $- eParser ".inverse. 42" `shouldBe'` unExp-- let binOp = BinCustom ".xor."- it "parses binary custom operator" $ do- let expected = ExpBinary () u binOp (intGen 24) (intGen 42)- eParser "24 .xor. 42" `shouldBe'` expected-- it "parses mixed unary custom operator" $ do- let binExp = ExpBinary () u binOp unExp (intGen 24)- eParser ".inverse. 42 .xor. 24" `shouldBe'` binExp-- it "parses data ref" $ do- let range = fromList () [ IxSingle () u Nothing $ intGen 10 ]- sub = ExpSubscript () u (varGen "y") range- innerRefExp = ExpDataRef () u (varGen "x") sub- exp = ExpDataRef () u innerRefExp (varGen "z")- eParser "x % y(10) % z" `shouldBe'` exp-- it "parses section subscript" $ do- let range = [ IxSingle () u Nothing $ intGen 10- , IxRange () u Nothing (Just $ intGen 1) (Just $ intGen 2)- , IxSingle () u Nothing $ varGen "y" ]- exp = ExpSubscript () u (varGen "x") (fromList () range)- eParser "x (10, : 1 : 2, y)" `shouldBe'` exp-- describe "Statement" $ do- it "data ref assignment" $ do- let indicies = AList () u [ IxSingle () u Nothing (intGen 1) ]- subs = ExpSubscript () u (varGen "x") indicies- lhs = ExpDataRef () u subs (varGen "y")- st = StExpressionAssign () u lhs (intGen 1)- sParser "x(1) % y = 1" `shouldBe'` st-- it "parses pause statements" $ do- let stPause = StPause () u Nothing- stStr = "PAUSE"- sParser stStr `shouldBe'` stPause-- it "parses pause statements with expression" $ do- let stPause = StPause () u (Just (strGen "MESSAGE"))- stStr = "PAUSE \"MESSAGE\""- sParser stStr `shouldBe'` stPause-- it "parses declaration with attributes" $ do- let typeSpec = TypeSpec () u TypeReal Nothing- attrs = AList () u [ AttrExternal () u- , AttrIntent () u Out- , AttrDimension () u $ AList () u- [ DimensionDeclarator () u- (Just $ intGen 3) (Just $ intGen 10)- ]- ]- declarators = AList () u [ declVarGen "x", declVarGen "y"]- expected = StDeclaration () u typeSpec (Just attrs) declarators- stStr = "real, external, intent (out), dimension (3:10) :: x, y"- sParser stStr `shouldBe'` expected-- it "parses declaration with old syntax" $ do- let typeSpec = TypeSpec () u TypeLogical Nothing- declarators = AList () u [ declVarGen "x", declVarGen "y"]- expected = StDeclaration () u typeSpec Nothing declarators- stStr = "logical x, y"- sParser stStr `shouldBe'` expected-- it "parses declaration with initialisation" $- let typeSpec = TypeSpec () u TypeComplex Nothing- init' = ExpValue () u (ValComplex (intGen 24) (realGen (42.0::Double)))- declarators = AList () u- [ declVariable () u (varGen "x") Nothing (Just init') ]- expected = StDeclaration () u typeSpec Nothing declarators- stStr = "complex :: x = (24, 42.0)"- in sParser stStr `shouldBe'` expected-- it "parses declaration of custom type" $ do- let typeSpec = TypeSpec () u (TypeCustom "meinetype") Nothing- declarators = AList () u [declVarGen "x"]- expected = StDeclaration () u typeSpec Nothing declarators- stStr = "type (MeineType) :: x"- sParser stStr `shouldBe'` expected-- it "parses declaration type with kind selector" $ do- let selector = Selector () u Nothing (Just $ varGen "hello")- typeSpec = TypeSpec () u TypeInteger (Just selector)- declarators = AList () u [declVarGen "x"]- expected = StDeclaration () u typeSpec Nothing declarators- stStr = "integer (hello) :: x"- sParser stStr `shouldBe'` expected-- it "parses intent statement" $ do- let stStr = "intent (inout) :: a"- expected = StIntent () u InOut (fromList () [ varGen "a" ])- sParser stStr `shouldBe'` expected-- it "parses optional statement" $ do- let stStr = "optional x"- expected = StOptional () u (fromList () [ varGen "x" ])- sParser stStr `shouldBe'` expected-- it "parses public statement" $ do- let stStr = "public :: x"- expected = StPublic () u (Just $ fromList () [ varGen "x" ])- sParser stStr `shouldBe'` expected-- it "parses public assignment" $ do- let expected = StPublic () u (Just $ fromList () [ assVal ])- sParser "public :: assignment (=)" `shouldBe'` expected-- it "parses private statement" $- sParser "private" `shouldBe'` StPrivate () u Nothing-- it "parses private operator" $ do- let expected = StPrivate () u (Just $ fromList () [ opGen "*" ])- sParser "private operator ( * )" `shouldBe'` expected-- it "parses save statement" $ do- let list = [ varGen "hello", varGen "bye" ]- expected = StSave () u (Just $ fromList () list)- stStr = "save /hello/, bye"- sParser stStr `shouldBe'` expected-- it "parses parameter statement" $ do- let ass1 = declVariable () u (varGen "x") Nothing (Just $ intGen 10)- ass2 = declVariable () u (varGen "y") Nothing (Just $ intGen 20)- expected = StParameter () u (fromList () [ ass1, ass2 ])- sParser "parameter (x = 10, y = 20)" `shouldBe'` expected-- describe "Implicit" $ do- it "parses implicit none" $ do- let st = StImplicit () u Nothing- sParser "implicit none" `shouldBe'` st-- it "parses implicit with single" $ do- let typeSpec = TypeSpec () u TypeCharacter Nothing- impEls = [ ImpCharacter () u "k" ]- impLists = [ ImpList () u typeSpec (fromList () impEls) ]- st = StImplicit () u (Just $ fromList () impLists)- sParser "implicit character (k)" `shouldBe'` st-- it "parses implicit with range" $ do- let typeSpec = TypeSpec () u TypeLogical Nothing- impEls = [ ImpRange () u "x" "z" ]- impLists = [ ImpList () u typeSpec (fromList () impEls) ]- st = StImplicit () u (Just $ fromList () impLists)- sParser "implicit logical (x-z)" `shouldBe'` st-- it "parses implicit statement" $ do- let typeSpec1 = TypeSpec () u TypeCharacter Nothing- typeSpec2 = TypeSpec () u TypeInteger Nothing- impEls1 = [ ImpCharacter () u "s", ImpCharacter () u "a" ]- impEls2 = [ ImpRange () u "x" "z" ]- impLists = [ ImpList () u typeSpec1 (fromList () impEls1)- , ImpList () u typeSpec2 (fromList () impEls2) ]- st = StImplicit () u (Just $ fromList () impLists)- sParser "implicit character (s, a), integer (x-z)" `shouldBe'` st-- describe "Data" $ do- it "parses vanilla" $ do- let nlist = fromList () [ varGen "x", varGen "y" ]- vlist = fromList () [ intGen 1, intGen 2 ]- list = [ DataGroup () u nlist vlist ]- expected = StData () u (fromList () list)- stStr = "data x,y/1,2/"- sParser stStr `shouldBe'` expected-- describe "Delimeter" $ do- let [ nlist1, vlist1 ] =- map (fromList () . return) [ varGen "x", intGen 1 ]- [ nlist2, vlist2 ] =- map (fromList () . return) [ varGen "y", intGen 2 ]- list = [ DataGroup () u nlist1 vlist1- , DataGroup () u nlist2 vlist2 ]- expected = StData () u (fromList () list)-- it "parses comma delimited init groups" $- sParser "data x/1/, y/2/" `shouldBe'` expected-- it "parses non-comma delimited init groups" $- sParser "data x/1/ y/2/" `shouldBe'` expected-- describe "Namelist" $ do- let groupNames = [ ExpValue () u (ValVariable "something")- , ExpValue () u (ValVariable "other") ]- itemss = [ fromList () [ varGen "a", varGen "b", varGen "c" ]- , fromList () [ varGen "y" ] ]- st = StNamelist () u $- fromList () [ Namelist () u (head groupNames) (head itemss)- , Namelist () u (last groupNames) (last itemss) ]-- it "parses namelist statement (comma delimited) (1)" $- sParser "namelist /something/a,b,c,/other/y" `shouldBe'` st-- it "parses namelist statement (2)" $- sParser "namelist /something/a,b,c/other/y" `shouldBe'` st-- describe "Common" $ do- let commonNames = [ ExpValue () u (ValVariable "something")- , ExpValue () u (ValVariable "other") ]- itemss = [ fromList () [ declVarGen "a", declVarGen "b", declVarGen "c" ]- , fromList () [ declVarGen "y" ] ]- st = StCommon () u $ fromList ()- [ CommonGroup () u Nothing (fromList () [ declVarGen "q" ])- , CommonGroup () u (Just $ head commonNames) (head itemss)- , CommonGroup () u (Just $ last commonNames) (last itemss) ]-- it "parses common statement (comma delimited) (1)" $- sParser "common q /something/a,b,c, /other/y" `shouldBe'` st-- it "parses common statement (2)" $- sParser "common q /something/a,b,c /other/y" `shouldBe'` st-- it "parses equivalence statement" $ do- let eqALists = fromList ()- [ fromList ()- [ let indicies = fromList () [ IxSingle () u Nothing (intGen 1) ]- in ExpSubscript () u (varGen "a") indicies- , varGen "x"- ]- , fromList ()- [ varGen "y"- , varGen "z"- , let indicies = fromList () [ IxRange () u (Just $ intGen 1)- (Just $ intGen 42)- Nothing ]- in ExpSubscript () u (varGen "d") indicies- ]- ]- let st = StEquivalence () u eqALists- sParser "equivalence (a(1), x), (y, z, d(1:42))" `shouldBe'` st-- describe "Dynamic allocation" $ do- it "parses allocate statement" $ do- let opt = AOStat () u (varGen "a")- allocs = fromList ()- [ varGen "x"- , ExpDataRef () u (varGen "st") (varGen "part")- ]- let s = StAllocate () u Nothing allocs (Just (AList () u [opt]))- sParser "allocate (x, st % part, STAT = a)" `shouldBe'` s-- it "parses deallocate statement" $ do- let opt = AOStat () u (varGen "a")- allocs = fromList ()- [ let indicies = fromList () [ IxSingle () u Nothing (intGen 20) ]- in ExpSubscript () u (varGen "smt") indicies- ]- s = StDeallocate () u allocs Nothing- s' = StDeallocate () u allocs (Just (AList () u [opt]))- sParser "deallocate (smt ( 20 ))" `shouldBe'` s- sParser "deallocate (smt ( 20 ), stat=a)" `shouldBe'` s'-- it "parses nullify statement" $ do- let s = StNullify () u (fromList () [ varGen "x" ])- sParser "nullify (x)" `shouldBe'` s-- it "parses pointer assignment" $ do- let src = ExpDataRef () u (varGen "x") (varGen "y")- st = StPointerAssign () u src (varGen "exp")- sParser "x % y => exp" `shouldBe'` st-- describe "Where" $ do- it "parses where statement" $ do- let exp = ExpBinary () u Subtraction (varGen "temp") (varGen "r_temp")- pred = ExpBinary () u GT (varGen "temp") (intGen 100)- assignment = StExpressionAssign () u (varGen "temp") exp- st = StWhere () u pred assignment- sParser "where (temp > 100) temp = temp - r_temp"`shouldBe'` st-- describe "Where block" $ do- it "parses where construct statement" $- sParser "where (.true.)" `shouldBe'` StWhereConstruct () u Nothing valTrue-- it "parses elsewhere statement" $- sParser "elsewhere" `shouldBe'` StElsewhere () u Nothing Nothing-- it "parses elsewhere statement" $ do- let exp = ExpBinary () u GT (varGen "a") (varGen "b")- sParser "elsewhere (a > b)" `shouldBe'` StElsewhere () u Nothing (Just exp)-- it "parses endwhere statement" $- sParser "endwhere" `shouldBe'` StEndWhere () u Nothing-- describe "If" $ do- let stPrint = StPrint () u starVal (Just $ fromList () [ ExpValue () u (ValString "foo")])- it "parser if block" $- let ifBlockSrc = unlines [ "if (.false.) then", "print *, 'foo'", "end if"]- in blParser ifBlockSrc `shouldBe'` BlIf () u Nothing Nothing [Just valFalse] [[BlStatement () u Nothing stPrint]] Nothing-- it "parses named if block" $ do- let ifBlockSrc = unlines [ "mylabel : if (.true.) then", "print *, 'foo'", "end if mylabel"]- ifBlock = BlIf () u Nothing (Just "mylabel") [Just valTrue] [[BlStatement () u Nothing stPrint]] Nothing- blParser ifBlockSrc `shouldBe'` ifBlock-- it "parses if-else block with inline comments (stripped)" $- let ifBlockSrc = unlines [ "if (.false.) then ! comment if", "print *, 'foo'", "else ! comment else", "print *, 'foo'", "end if ! comment end"]- in blParser ifBlockSrc `shouldBe'` BlIf () u Nothing Nothing [Just valFalse, Nothing] [[BlStatement () u Nothing stPrint], [BlStatement () u Nothing stPrint]] Nothing-- it "parses logical if statement" $ do- let assignment = StExpressionAssign () u (varGen "a") (varGen "b")- stIf = StIfLogical () u valTrue assignment- sParser "if (.true.) a = b" `shouldBe'` stIf-- it "parses arithmetic if statement" $ do- let stIf = StIfArithmetic () u (varGen "x") (intGen 1)- (intGen 2)- (intGen 3)- sParser "if (x) 1, 2, 3" `shouldBe'` stIf-- describe "Case" $ do- let printArgs str = Just $ AList () u [ExpValue () u $ ValString str]- printStmt = StPrint () u (ExpValue () u ValStar) . printArgs- printBlock = BlStatement () u Nothing . printStmt- ind2 = AList () u . pure $ IxSingle () u Nothing $ intGen 2- ind3Plus = AList () u . pure $ IxRange () u (Just $ intGen 3) Nothing Nothing- conds = [Just ind2, Just ind3Plus, Nothing]- it "unlabelled case block (with inline comments to be stripped)" $ do- let src = unlines [ "select case (x) ! comment select"- , "! full line before first case (unrepresentable)"- , "case (2) ! comment case 1"- , "print *, 'foo'"- , "case (3:) ! comment case 2"- , "print *, 'bar'"- , "case default ! comment case 3"- , "print *, 'baz'"- , "end select ! comment end"- ]- blocks = (fmap . fmap) printBlock [["foo"], ["bar"], ["baz"]]- block = BlCase () u Nothing Nothing (varGen "x") conds blocks Nothing- blParser src `shouldBe'` block- it "labelled case block (with inline comments to be stripped" $ do- let src = unlines [ "10 mylabel: select case (x) ! comment select"- , "20 case (2) ! comment case 1"- , "30 print *, 'foo'"- , "40 case (3:) ! comment case 2"- , "50 print *, 'bar'"- , "60 case default ! comment case 3"- , "70 print *, 'baz'"- , "80 end select mylabel ! comment end"- ]- blocks = (fmap . fmap)- (\(label, arg) -> BlStatement () u (Just $ intGen label) $ printStmt arg)- [[(30, "foo")], [(50, "bar")], [(70, "baz")]]- block = BlCase () u- (Just $ intGen 10) (Just "mylabel") (varGen "x")- conds blocks- (Just $ intGen 80)- blParser src `shouldBe'` block-- describe "Do" $ do- it "parses do statement with label" $ do- let assign = StExpressionAssign () u (varGen "i") (intGen 0)- doSpec = DoSpecification () u assign (intGen 42) Nothing- st = StDo () u Nothing (Just $ intGen 24) (Just doSpec)- sParser "do 24, i = 0, 42" `shouldBe'` st-- it "parses do statement without label" $ do- let assign = StExpressionAssign () u (varGen "i") (intGen 0)- doSpec = DoSpecification () u assign (intGen 42) Nothing- st = StDo () u Nothing Nothing (Just doSpec)- sParser "do i = 0, 42" `shouldBe'` st-- it "parses infinite do" $ do- let st = StDo () u Nothing Nothing Nothing- sParser "do" `shouldBe'` st-- it "parses end do statement" $ do- let st = StEnddo () u (Just "constructor")- sParser "end do constructor" `shouldBe'` st-- describe "DO WHILE" $ do- it "parses unnamed do while statement" $ do- let st = StDoWhile () u Nothing Nothing valTrue- sParser "do while (.true.)" `shouldBe'` st-- it "parses named do while statement" $ do- let st = StDoWhile () u (Just "name") Nothing valTrue- sParser "name: do while (.true.)" `shouldBe'` st-- it "parses unnamed labelled do while statement" $ do- let st = StDoWhile () u Nothing (Just (intGen 999)) valTrue- sParser "do 999 while (.true.)" `shouldBe'` st-- describe "Goto" $ do- it "parses vanilla goto" $ do- let st = StGotoUnconditional () u (intGen 999)- sParser "goto 999" `shouldBe'` st-- it "parses computed goto" $ do- let list = fromList () [ intGen 10, intGen 20, intGen 30 ]- st = StGotoComputed () u list (intGen 20)- sParser "goto (10, 20, 30) 20" `shouldBe'` st-- it "parses assigned goto" $ do- let list = fromList () [ intGen 10, intGen 20, intGen 30 ]- st = StGotoAssigned () u (varGen "i") (Just list)- sParser "goto i, (10, 20, 30)" `shouldBe'` st-- it "parses label assignment" $ do- let st = StLabelAssign () u (intGen 20) (varGen "l")- sParser "assign 20 to l" `shouldBe'` st-- describe "IO" $ do- it "parses vanilla print" $ do- let st = StPrint () u starVal (Just $ fromList () [ varGen "hex" ])- sParser "print *, hex" `shouldBe'` st-- it "parses write with implied do" $ do- let cp1 = ControlPair () u Nothing (intGen 10)- cp2 = ControlPair () u (Just "format") (varGen "x")- ciList = fromList () [ cp1, cp2 ]- assign = StExpressionAssign () u (varGen "i") (intGen 1)- doSpec = DoSpecification () u assign (intGen 42) (Just $ intGen 2)- alist = fromList () [ varGen "i", varGen "j" ]- outList = fromList () [ ExpImpliedDo () u alist doSpec ]- st = StWrite () u ciList (Just outList)- sParser "write (10, FORMAT = x) (i, j, i = 1, 42, 2)" `shouldBe'` st-- it "parses use statement with renames" $ do- let renames = fromList ()- [ UseRename () u (varGen "sprod") (varGen "prod")- , UseRename () u (varGen "a") (varGen "b") ]- st = StUse () u (varGen "stats_lib") Nothing Permissive (Just renames)- sParser "use stats_lib, sprod => prod, a => b" `shouldBe'` st-- it "parses use statement with only list" $ do- let onlys = fromList ()- [ UseID () u (varGen "a")- , UseRename () u (varGen "b") (varGen "c")- , UseID () u (ExpValue () u (ValOperator "+"))- , UseID () u (ExpValue () u ValAssignment) ]- st = StUse () u (varGen "stats_lib") Nothing Exclusive (Just onlys)- sParser "use stats_lib, only: a, b => c, operator(+), assignment(=)" `shouldBe'` st-- specFreeFormCommon sParser eParser
− test/Language/Fortran/Parser/Fortran95Spec.hs
@@ -1,660 +0,0 @@-module Language.Fortran.Parser.Fortran95Spec (spec) where--import Prelude hiding (GT, EQ, exp, pred)--import Test.Hspec-import TestUtil-import Language.Fortran.Parser.FreeFormCommon--import Control.Exception (evaluate)--import Language.Fortran.AST-import Language.Fortran.ParserMonad-import Language.Fortran.Lexer.FreeForm-import Language.Fortran.Parser.Fortran95-import qualified Data.List as List-import Data.Foldable(forM_)-import qualified Data.ByteString.Char8 as B--{-# ANN module "HLint: ignore Reduce duplication" #-}--eParser :: String -> Expression ()-eParser sourceCode =- case evalParse statementParser parseState of- (StExpressionAssign _ _ _ e) -> e- _ -> error "unhandled evalParse"- where- paddedSourceCode = B.pack $ " a = " ++ sourceCode- parseState = initParseState paddedSourceCode Fortran95 "<unknown>"--sParser :: String -> Statement ()-sParser sourceCode =- evalParse statementParser $ initParseState (B.pack sourceCode) Fortran95 "<unknown>"--blParser :: String -> Block ()-blParser sourceCode =- evalParse blockParser $ initParseState (B.pack sourceCode) Fortran95 "<unknown>"--fParser :: String -> ProgramUnit ()-fParser sourceCode =- evalParse functionParser $ initParseState (B.pack sourceCode) Fortran95 "<unknown>"--{- Useful for parser debugging; Lexes the given source code.-fTok :: String -> [Token]-fTok sourceCode = collectFreeTokens Fortran95 $ B.pack sourceCode--}--{-- - Given a list of values, find every combination of those values:- - combination [1,2] = [[], [1], [2], [1,2], [2,1]]- -}-combination :: [a] -> [[a]]-combination = foldr ((++) . List.permutations) [] . List.subsequences--spec :: Spec-spec =- describe "Fortran 95 Parser" $ do- describe "Function" $ do- let puFunction = PUFunction () u- fType = Nothing- fSuf = emptySuffixes- fPreSuf = emptyPrefixSuffix- fName = "f"- fArgs = Nothing- fRes = Nothing- fBody = []- fSub = Nothing-- describe "End" $ do- it "parses simple functions ending with \"end function [function name]\"" $ do- let expected = puFunction fType fPreSuf fName fArgs fRes fBody fSub- fStr = init $ unlines ["function f()"- , "end function f" ]- fParser fStr `shouldBe'` expected-- it "parses simple functions ending with \"end\"" $ do- let expected = puFunction fType fPreSuf fName fArgs fRes fBody fSub- fStr = init $ unlines ["function f()"- , "end" ]- fParser fStr `shouldBe'` expected-- it "parses simple functions ending with \"end function\"" $ do- let expected = puFunction fType fPreSuf fName fArgs fRes fBody fSub- fStr = init $ unlines ["function f()"- , "end function" ]- fParser fStr `shouldBe'` expected--- it "parses functions with return type specs" $ do- let fType' = Just $ TypeSpec () u TypeInteger Nothing- expected = puFunction fType' fPreSuf fName fArgs fRes fBody fSub- fStr = init $ unlines ["integer function f()"- , "end function f" ]- fParser fStr `shouldBe'` expected-- describe "parses function options (recursive, pure, elemental)" $ do- let options_list = map unzip $ combination- [ ("recursive ", PfxRecursive () u)- , ("pure ", PfxPure () u)- , ("elemental ", PfxElemental () u) ]-- forM_ options_list (\(strs, opts) -> do- let isElem (PfxElemental {}) = True; isElem _ = False- isRec (PfxRecursive {}) = True; isRec _ = False- str = concat strs- fStr = str ++ init (unlines ["function f()", "end"])- pfx = fromList' () opts- --let expected = puFunction fType- if any isElem opts && any isRec opts- then- it ("Shouldn't parse: " ++ show fStr ++ ": " ++ show opts) $- evaluate (fParser fStr) `shouldThrow` anyIOException- else- it ("Should parse: " ++ show fStr ++ ": " ++ show opts) $ do- let expected' = puFunction fType (pfx, fSuf) fName fArgs fRes fBody fSub- fParser fStr `shouldBe'` expected'- )-- it "parses functions with a list of arguments" $ do- let fArgs' = Just $ AList () u [ varGen "x", varGen "y", varGen "z" ]- expected = puFunction fType fPreSuf fName fArgs' fRes fBody fSub- fStr = init $ unlines ["function f(x, y, z)"- , "end function f" ]- fParser fStr `shouldBe'` expected-- it "parses functions with a result variable" $ do- let fRes' = Just $ varGen "i"- expected = puFunction fType fPreSuf fName fArgs fRes' fBody fSub- fStr = init $ unlines ["function f() result(i)"- , "end function f" ]- fParser fStr `shouldBe'` expected-- it "parses functions with function bodies" $ do- let decrementRHS = ExpBinary () u Subtraction (varGen "i") (intGen 1)- f1 = StPrint () u starVal (Just $ AList () u [ varGen "i" ])- f2 = StExpressionAssign () u (varGen "i") decrementRHS- fBody' = [ BlStatement () u Nothing f1 , BlStatement () u Nothing f2 ]- expected = puFunction fType fPreSuf fName fArgs fRes fBody' fSub- fStr = init $ unlines ["function f()"- , " print *, i"- , " i = (i - 1)"- , "end function f" ]- fParser fStr `shouldBe'` expected-- it "parses complex functions" $ do- let fType' = Just $ TypeSpec () u TypeInteger Nothing- fArgs' = Just $ AList () u [ varGen "x", varGen "y", varGen "z" ]- fRes' = Just $ varGen "i"- decrementRHS = ExpBinary () u Subtraction (varGen "i") (intGen 1)- f1 = StPrint () u starVal (Just $ AList () u [ varGen "i" ])- f2 = StExpressionAssign () u (varGen "i") decrementRHS- fBody' = [ BlStatement () u Nothing f1 , BlStatement () u Nothing f2 ]- expected = puFunction fType' fPreSuf fName fArgs' fRes' fBody' fSub- fStr = init $ unlines [ "integer function f(x, y, z) result(i)"- , " print *, i"- , " i = (i - 1)"- , "end function f" ]- fParser fStr `shouldBe'` expected-- describe "Expression" $ do- it "parses logical literal without kind parameter" $ do- eParser ".true." `shouldBe'` valTrue-- it "parses logical literal with kind parameter" $ do- let kp = ExpValue () u (ValVariable "kind")- eParser ".false._kind" `shouldBe'` valFalse' kp-- it "parses array initialisation exp" $ do- let list = AList () u [ intGen 1, intGen 2, intGen 3, intGen 4 ]- eParser "(/ 1, 2, 3, 4 /)" `shouldBe'` ExpInitialisation () u list-- describe "Custom operator" $ do- let unOp = UnCustom ".inverse."- unExp = ExpUnary () u unOp $ intGen 42-- it "parses unary custom operator" $- eParser ".inverse. 42" `shouldBe'` unExp-- let binOp = BinCustom ".xor."- it "parses binary custom operator" $ do- let expected = ExpBinary () u binOp (intGen 24) (intGen 42)- eParser "24 .xor. 42" `shouldBe'` expected-- it "parses mixed unary custom operator" $ do- let binExp = ExpBinary () u binOp unExp (intGen 24)- eParser ".inverse. 42 .xor. 24" `shouldBe'` binExp-- it "parses data ref" $ do- let range = fromList () [ IxSingle () u Nothing $ intGen 10 ]- sub = ExpSubscript () u (varGen "y") range- innerRefExp = ExpDataRef () u (varGen "x") sub- exp = ExpDataRef () u innerRefExp (varGen "z")- eParser "x % y(10) % z" `shouldBe'` exp-- it "parses section subscript" $ do- let range = [ IxSingle () u Nothing $ intGen 10- , IxRange () u Nothing (Just $ intGen 1) (Just $ intGen 2)- , IxSingle () u Nothing $ varGen "y" ]- exp = ExpSubscript () u (varGen "x") (fromList () range)- eParser "x (10, : 1 : 2, y)" `shouldBe'` exp-- describe "Statement" $ do- it "data ref assignment" $ do- let indicies = AList () u [ IxSingle () u Nothing (intGen 1) ]- subs = ExpSubscript () u (varGen "x") indicies- lhs = ExpDataRef () u subs (varGen "y")- st = StExpressionAssign () u lhs (intGen 1)- sParser "x(1) % y = 1" `shouldBe'` st-- it "doesn't parse assign statements" $ do- let stStr = "ASSIGN 1 \"LABEL\""- evaluate (sParser stStr) `shouldThrow` anyIOException-- it "doesn't parse pause statements" $ do- let stStr = "PAUSE"- evaluate (sParser stStr) `shouldThrow` anyIOException-- it "doesn't parse pause statements with expression" $ do- let stStr = "PAUSE \"MESSAGE\""- evaluate (sParser stStr) `shouldThrow` anyIOException-- it "parses declaration with attributes" $ do- let typeSpec = TypeSpec () u TypeReal Nothing- attrs = AList () u [ AttrExternal () u- , AttrIntent () u Out- , AttrDimension () u $ AList () u- [ DimensionDeclarator () u- (Just $ intGen 3) (Just $ intGen 10)- ]- ]- declarators = AList () u- [ declVariable () u (varGen "x") Nothing Nothing- , declVariable () u (varGen "y") Nothing Nothing ]- expected = StDeclaration () u typeSpec (Just attrs) declarators- stStr = "real, external, intent (out), dimension (3:10) :: x, y"- sParser stStr `shouldBe'` expected-- it "parses declaration with old syntax" $ do- let typeSpec = TypeSpec () u TypeLogical Nothing- declarators = AList () u- [ declVariable () u (varGen "x") Nothing Nothing- , declVariable () u (varGen "y") Nothing Nothing ]- expected = StDeclaration () u typeSpec Nothing declarators- stStr = "logical x, y"- sParser stStr `shouldBe'` expected-- it "parses declaration with initialisation" $ do- let typeSpec = TypeSpec () u TypeComplex Nothing- init' = ExpValue () u (ValComplex (intGen 24) (realGen (42.0::Double)))- declarators = AList () u- [ declVariable () u (varGen "x") Nothing (Just init') ]- expected = StDeclaration () u typeSpec Nothing declarators- stStr = "complex :: x = (24, 42.0)"- sParser stStr `shouldBe'` expected-- it "parses declaration of custom type" $ do- let typeSpec = TypeSpec () u (TypeCustom "meinetype") Nothing- declarators = AList () u- [ declVariable () u (varGen "x") Nothing Nothing ]- expected = StDeclaration () u typeSpec Nothing declarators- stStr = "type (MeineType) :: x"- sParser stStr `shouldBe'` expected-- it "parses declaration type with kind selector" $ do- let selector = Selector () u Nothing (Just $ varGen "hello")- typeSpec = TypeSpec () u TypeInteger (Just selector)- declarators = AList () u- [ declVariable () u (varGen "x") Nothing Nothing ]- expected = StDeclaration () u typeSpec Nothing declarators- stStr = "integer (hello) :: x"- sParser stStr `shouldBe'` expected-- it "parses intent statement" $ do- let stStr = "intent (inout) :: a"- expected = StIntent () u InOut (fromList () [ varGen "a" ])- sParser stStr `shouldBe'` expected-- it "parses optional statement" $ do- let stStr = "optional x"- expected = StOptional () u (fromList () [ varGen "x" ])- sParser stStr `shouldBe'` expected-- it "parses public statement" $ do- let stStr = "public :: x"- expected = StPublic () u (Just $ fromList () [ varGen "x" ])- sParser stStr `shouldBe'` expected-- it "parses public assignment" $ do- let expected = StPublic () u (Just $ fromList () [ assVal ])- sParser "public :: assignment (=)" `shouldBe'` expected-- it "parses private statement" $- sParser "private" `shouldBe'` StPrivate () u Nothing-- it "parses private operator" $ do- let expected = StPrivate () u (Just $ fromList () [ opGen "*" ])- sParser "private operator ( * )" `shouldBe'` expected-- it "parses save statement" $ do- let list = [ varGen "hello", varGen "bye" ]- expected = StSave () u (Just $ fromList () list)- stStr = "save /hello/, bye"- sParser stStr `shouldBe'` expected-- it "parses parameter statement" $ do- let ass1 = declVariable () u (varGen "x") Nothing (Just $ intGen 10)- ass2 = declVariable () u (varGen "y") Nothing (Just $ intGen 20)- expected = StParameter () u (fromList () [ ass1, ass2 ])- sParser "parameter (x = 10, y = 20)" `shouldBe'` expected-- describe "FORALL blocks" $ do- let stride = Just $ ExpBinary () u NE (varGen "i") (intGen 2)- tripletSpecList = [("i", intGen 1, varGen "n", stride)]-- it "parses basic FORALL blocks" $ do- let stStr = "FORALL (I=1:N, I /= 2)"- expected = StForall () u Nothing (ForallHeader tripletSpecList Nothing)- sParser stStr `shouldBe'` expected-- describe "FORALL statements" $ do- let stride = Just $ ExpBinary () u NE (varGen "i") (intGen 2)- tripletSpecList = [("i", intGen 1, varGen "n", stride)]- --let varI = IxSingle () u Nothing (varGen "i")- --let expSub1 = ExpSubscript () u (varGen "a") (AList () u [varI, varI])- --let expSub2 = ExpSubscript () u (varGen "x") (AList () u [varI])- --let eAssign = StExpressionAssign () u expSub1 expSub2-- it "parses basic FORALL statements" $ do- let stStr = "FORALL (I=1:N, I /= 2)" -- A(I,I) = X(I)"- expected = StForall () u Nothing (ForallHeader tripletSpecList Nothing)-- eAssign- sParser stStr `shouldBe'` expected-- describe "ENDFORALL statements" $ do- it "parses FORALL end statements" $ do- let stStr = "ENDFORALL"- expected = StEndForall () u Nothing- sParser stStr `shouldBe'` expected-- it "parses FORALL end statements with label" $ do- let stStr = "ENDFORALL A"- expected = StEndForall () u $ Just "a"- sParser stStr `shouldBe'` expected-- describe "Implicit" $ do- it "parses implicit none" $ do- let st = StImplicit () u Nothing- sParser "implicit none" `shouldBe'` st-- it "parses implicit with single" $ do- let typeSpec = TypeSpec () u TypeCharacter Nothing- impEls = [ ImpCharacter () u "k" ]- impLists = [ ImpList () u typeSpec (fromList () impEls) ]- st = StImplicit () u (Just $ fromList () impLists)- sParser "implicit character (k)" `shouldBe'` st-- it "parses implicit with range" $ do- let typeSpec = TypeSpec () u TypeLogical Nothing- impEls = [ ImpRange () u "x" "z" ]- impLists = [ ImpList () u typeSpec (fromList () impEls) ]- st = StImplicit () u (Just $ fromList () impLists)- sParser "implicit logical (x-z)" `shouldBe'` st-- it "parses implicit statement" $ do- let typeSpec1 = TypeSpec () u TypeCharacter Nothing- typeSpec2 = TypeSpec () u TypeInteger Nothing- impEls1 = [ ImpCharacter () u "s", ImpCharacter () u "a" ]- impEls2 = [ ImpRange () u "x" "z" ]- impLists = [ ImpList () u typeSpec1 (fromList () impEls1)- , ImpList () u typeSpec2 (fromList () impEls2) ]- st = StImplicit () u (Just $ fromList () impLists)- sParser "implicit character (s, a), integer (x-z)" `shouldBe'` st-- describe "Data" $ do- it "parses vanilla" $ do- let nlist = fromList () [ varGen "x", varGen "y" ]- vlist = fromList () [ intGen 1, intGen 2 ]- list = [ DataGroup () u nlist vlist ]- expected = StData () u (fromList () list)- stStr = "data x,y/1,2/"- sParser stStr `shouldBe'` expected-- describe "Delimeter" $ do- let [ nlist1, vlist1 ] =- map (fromList () . return) [ varGen "x", intGen 1 ]- [ nlist2, vlist2 ] =- map (fromList () . return) [ varGen "y", intGen 2 ]- list = [ DataGroup () u nlist1 vlist1- , DataGroup () u nlist2 vlist2 ]- expected = StData () u (fromList () list)-- it "parses comma delimited init groups" $- sParser "data x/1/, y/2/" `shouldBe'` expected-- it "parses non-comma delimited init groups" $- sParser "data x/1/ y/2/" `shouldBe'` expected-- describe "Namelist" $ do- let groupNames = [ ExpValue () u (ValVariable "something")- , ExpValue () u (ValVariable "other") ]- itemss = [ fromList () [ varGen "a", varGen "b", varGen "c" ]- , fromList () [ varGen "y" ] ]- st = StNamelist () u $- fromList () [ Namelist () u (head groupNames) (head itemss)- , Namelist () u (last groupNames) (last itemss) ]-- it "parses namelist statement (comma delimited) (1)" $- sParser "namelist /something/a,b,c,/other/y" `shouldBe'` st-- it "parses namelist statement (2)" $- sParser "namelist /something/a,b,c/other/y" `shouldBe'` st-- describe "Common" $ do- let commonNames = [ ExpValue () u (ValVariable "something")- , ExpValue () u (ValVariable "other") ]- itemss = [ fromList () [ declVarGen "a", declVarGen "b", declVarGen "c" ]- , fromList () [ declVarGen "y" ] ]- st = StCommon () u $ fromList ()- [ CommonGroup () u Nothing (fromList () [ declVarGen "q" ])- , CommonGroup () u (Just $ head commonNames) (head itemss)- , CommonGroup () u (Just $ last commonNames) (last itemss) ]-- it "parses common statement (comma delimited) (1)" $- sParser "common q /something/a,b,c, /other/y" `shouldBe'` st-- it "parses common statement (2)" $- sParser "common q /something/a,b,c /other/y" `shouldBe'` st-- it "parses equivalence statement" $ do- let eqALists = fromList ()- [ fromList ()- [ let indicies = fromList () [ IxSingle () u Nothing (intGen 1) ]- in ExpSubscript () u (varGen "a") indicies- , varGen "x"- ]- , fromList ()- [ varGen "y"- , varGen "z"- , let indicies = fromList () [ IxRange () u (Just $ intGen 1)- (Just $ intGen 42)- Nothing ]- in ExpSubscript () u (varGen "d") indicies- ]- ]- st = StEquivalence () u eqALists- sParser "equivalence (a(1), x), (y, z, d(1:42))" `shouldBe'` st-- describe "Dynamic allocation" $ do- it "parses allocate statement" $ do- let opt = AOStat () u (varGen "a")- allocs = fromList ()- [ varGen "x"- , ExpDataRef () u (varGen "st") (varGen "part")- ]- s = StAllocate () u Nothing allocs (Just (AList () u [opt]))- sParser "allocate (x, st % part, STAT = a)" `shouldBe'` s-- it "parses deallocate statement" $ do- let allocs = fromList ()- [ let indicies = fromList () [ IxSingle () u Nothing (intGen 20) ]- in ExpSubscript () u (varGen "smt") indicies- ]- s = StDeallocate () u allocs Nothing- sParser "deallocate (smt ( 20 ))" `shouldBe'` s-- it "parses nullify statement" $ do- let s = StNullify () u (fromList () [ varGen "x" ])- sParser "nullify (x)" `shouldBe'` s-- it "parses pointer assignment" $ do- let src = ExpDataRef () u (varGen "x") (varGen "y")- st = StPointerAssign () u src (varGen "exp")- sParser "x % y => exp" `shouldBe'` st-- describe "Where" $ do- it "parses where statement" $ do- let exp = ExpBinary () u Subtraction (varGen "temp") (varGen "r_temp")- pred = ExpBinary () u GT (varGen "temp") (intGen 100)- assignment = StExpressionAssign () u (varGen "temp") exp- st = StWhere () u pred assignment- sParser "where (temp > 100) temp = temp - r_temp"`shouldBe'` st-- describe "Where block" $ do- it "parses where construct statement" $- sParser "where (.true.)" `shouldBe'` StWhereConstruct () u Nothing valTrue-- it "parses elsewhere statement" $- sParser "elsewhere" `shouldBe'` StElsewhere () u Nothing Nothing-- it "parses elsewhere statement" $ do- let exp = ExpBinary () u GT (varGen "a") (varGen "b")- sParser "elsewhere (a > b)" `shouldBe'` StElsewhere () u Nothing (Just exp)-- it "parses endwhere statement" $- sParser "endwhere" `shouldBe'` StEndWhere () u Nothing-- describe "If" $ do- let stPrint = StPrint () u starVal (Just $ fromList () [ ExpValue () u (ValString "foo")])- it "parser if block" $- let ifBlockSrc = unlines [ "if (.false.) then", "print *, 'foo'", "end if"]- in blParser ifBlockSrc `shouldBe'` BlIf () u Nothing Nothing [Just valFalse] [[BlStatement () u Nothing stPrint]] Nothing-- it "parses named if block" $ do- let ifBlockSrc = unlines [ "mylabel : if (.true.) then", "print *, 'foo'", "end if mylabel"]- ifBlock = BlIf () u Nothing (Just "mylabel") [Just valTrue] [[BlStatement () u Nothing stPrint]] Nothing- blParser ifBlockSrc `shouldBe'` ifBlock-- it "parses if-else block with inline comments (stripped)" $- let ifBlockSrc = unlines [ "if (.false.) then ! comment if", "print *, 'foo'", "else ! comment else", "print *, 'foo'", "end if ! comment end"]- in blParser ifBlockSrc `shouldBe'` BlIf () u Nothing Nothing [Just valFalse, Nothing] [[BlStatement () u Nothing stPrint], [BlStatement () u Nothing stPrint]] Nothing-- it "parses logical if statement" $ do- let assignment = StExpressionAssign () u (varGen "a") (varGen "b")- stIf = StIfLogical () u valTrue assignment- sParser "if (.true.) a = b" `shouldBe'` stIf-- it "parses arithmetic if statement" $ do- let stIf = StIfArithmetic () u (varGen "x") (intGen 1)- (intGen 2)- (intGen 3)- sParser "if (x) 1, 2, 3" `shouldBe'` stIf-- describe "Case" $ do- let printArgs str = Just $ AList () u [ExpValue () u $ ValString str]- printStmt = StPrint () u (ExpValue () u ValStar) . printArgs- printBlock = BlStatement () u Nothing . printStmt- ind2 = AList () u . pure $ IxSingle () u Nothing $ intGen 2- ind3Plus = AList () u . pure $ IxRange () u (Just $ intGen 3) Nothing Nothing- conds = [Just ind2, Just ind3Plus, Nothing]- it "unlabelled case block (with inline comments to be stripped)" $ do- let src = unlines [ "select case (x) ! comment select"- , "! full line before first case (unrepresentable)"- , "case (2) ! comment case 1"- , "print *, 'foo'"- , "case (3:) ! comment case 2"- , "print *, 'bar'"- , "case default ! comment case 3"- , "print *, 'baz'"- , "end select ! comment end"- ]- blocks = (fmap . fmap) printBlock [["foo"], ["bar"], ["baz"]]- block = BlCase () u Nothing Nothing (varGen "x") conds blocks Nothing- blParser src `shouldBe'` block- it "labelled case block (with inline comments to be stripped" $ do- let src = unlines [ "10 mylabel: select case (x) ! comment select"- , "20 case (2) ! comment case 1"- , "30 print *, 'foo'"- , "40 case (3:) ! comment case 2"- , "50 print *, 'bar'"- , "60 case default ! comment case 3"- , "70 print *, 'baz'"- , "80 end select mylabel ! comment end"- ]- blocks = (fmap . fmap)- (\(label, arg) -> BlStatement () u (Just $ intGen label) $ printStmt arg)- [[(30, "foo")], [(50, "bar")], [(70, "baz")]]- block = BlCase () u- (Just $ intGen 10) (Just "mylabel") (varGen "x")- conds blocks- (Just $ intGen 80)- blParser src `shouldBe'` block-- describe "Do" $ do- it "parses do statement with label" $ do- let assign = StExpressionAssign () u (varGen "i") (intGen 0)- doSpec = DoSpecification () u assign (intGen 42) Nothing- st = StDo () u Nothing (Just $ intGen 24) (Just doSpec)- sParser "do 24, i = 0, 42" `shouldBe'` st-- it "parses do statement without label" $ do- let assign = StExpressionAssign () u (varGen "i") (intGen 0)- doSpec = DoSpecification () u assign (intGen 42) Nothing- st = StDo () u Nothing Nothing (Just doSpec)- sParser "do i = 0, 42" `shouldBe'` st-- it "parses infinite do" $ do- let st = StDo () u Nothing Nothing Nothing- sParser "do" `shouldBe'` st-- it "parses end do statement" $ do- let st = StEnddo () u (Just "constructor")- sParser "end do constructor" `shouldBe'` st-- describe "DO WHILE" $ do- it "parses unnamed do while statement" $ do- let st = StDoWhile () u Nothing Nothing valTrue- sParser "do while (.true.)" `shouldBe'` st-- it "parses named do while statement" $ do- let st = StDoWhile () u (Just "name") Nothing valTrue- sParser "name: do while (.true.)" `shouldBe'` st-- it "parses unnamed labelled do while statement" $ do- let st = StDoWhile () u Nothing (Just (intGen 999)) valTrue- sParser "do 999 while (.true.)" `shouldBe'` st-- describe "Goto" $ do- it "parses vanilla goto" $ do- let st = StGotoUnconditional () u (intGen 999)- sParser "goto 999" `shouldBe'` st-- it "parses computed goto" $ do- let list = fromList () [ intGen 10, intGen 20, intGen 30 ]- st = StGotoComputed () u list (intGen 20)- sParser "goto (10, 20, 30) 20" `shouldBe'` st-- it "doesn't parse assigned goto" $- evaluate (sParser "goto i, (10, 20, 30)") `shouldThrow` anyIOException-- it "doesn't parse label assignment" $- evaluate (sParser "assign 20 to l") `shouldThrow` anyIOException-- describe "IO" $ do- it "parses vanilla print" $ do- let st = StPrint () u starVal (Just $ fromList () [ varGen "hex" ])- sParser "print *, hex" `shouldBe'` st-- it "parses write with implied do" $ do- let cp1 = ControlPair () u Nothing (intGen 10)- cp2 = ControlPair () u (Just "format") (varGen "x")- ciList = fromList () [ cp1, cp2 ]- assign = StExpressionAssign () u (varGen "i") (intGen 1)- doSpec = DoSpecification () u assign (intGen 42) (Just $ intGen 2)- alist = fromList () [ varGen "i", varGen "j" ]- outList = fromList () [ ExpImpliedDo () u alist doSpec ]- st = StWrite () u ciList (Just outList)- sParser "write (10, FORMAT = x) (i, j, i = 1, 42, 2)" `shouldBe'` st-- it "parses use statement" $ do- let renames = fromList ()- [ UseRename () u (varGen "sprod") (varGen "prod")- , UseRename () u (varGen "a") (varGen "b") ]- st = StUse () u (varGen "stats_lib") Nothing Permissive (Just renames)- sParser "use stats_lib, sprod => prod, a => b" `shouldBe'` st-- it "parses value decl" $ do- let decls = [declVarGen "a", declVarGen "b"]- st = StValue () u (AList () u decls)- sParser "value a, b" `shouldBe'` st- sParser "value :: a, b" `shouldBe'` st-- it "parses value attribute" $ do- let decls = [declVarGen "a", declVarGen "b"]- ty = TypeSpec () u TypeInteger Nothing- attrs = [AttrValue () u]- st = StDeclaration () u ty (Just (AList () u attrs)) (AList () u decls)- sParser "integer, value :: a, b" `shouldBe'` st-- it "parses volatile decl" $ do- let decls = [declVarGen "a", declVarGen "b"]- st = StVolatile () u (AList () u decls)- sParser "volatile a, b" `shouldBe'` st- sParser "volatile :: a, b" `shouldBe'` st-- it "parses volatile attribute" $ do- let decls = [declVarGen "a", declVarGen "b"]- ty = TypeSpec () u TypeInteger Nothing- attrs = [AttrVolatile () u]- st = StDeclaration () u ty (Just (AList () u attrs)) (AList () u decls)- sParser "integer, volatile :: a, b" `shouldBe'` st-- specFreeFormCommon sParser eParser
+ test/Language/Fortran/Parser/Free/Common.hs view
@@ -0,0 +1,87 @@+{-| Common tests for free-form Fortran.++Fortran standards F90 and beyond are a lot more consistent than the+previous 2. As such, there is lots of shared parsing, and lots of shared+tests. This module encodes such shared/common tests, where no difference+in behaviour between parsers is be expected.+-}++module Language.Fortran.Parser.Free.Common ( specFreeCommon ) where++import TestUtil+import Test.Hspec++import Language.Fortran.AST+import Language.Fortran.AST.RealLit++specFreeCommon :: (String -> Statement A0) -> (String -> Expression A0) -> Spec+specFreeCommon sParser eParser =+ describe "Common Fortran 90+ tests" $ do+ describe "Literals" $ do+ describe "Logical" $ do+ it "parses logical literal without kind parameter" $ do+ eParser ".true." `shouldBe'` valTrue++ it "parses logical literal with kind parameter" $ do+ let kp = ExpValue () u (ValVariable "kind")+ eParser ".false._kind" `shouldBe'` valFalse' kp++ it "parses mixed-case logical literal" $ do+ eParser ".tRUe." `shouldBe'` valTrue++ -- Main parse testing is performed in @Language.Fortran.AST.RealLitSpec@.+ -- Here we mainly want to test kind parameter and sign behaviour.+ describe "Real" $ do+ let realLitExp r mkp = ExpValue () u (ValReal (parseRealLit r) mkp)+ it "parses various REAL literals" $ do+ eParser "1." `shouldBe'` realLitExp "1." Nothing+ eParser ".1e20_8" `shouldBe'` realLitExp ".1e20" (Just (intGen 8))++ it "parses \"negative\" real literal (unary op)" $ do+ eParser "-1.0d-1_k8" `shouldBe'` ExpUnary () u Minus (realLitExp "1.0d-1" (Just (varGen "k8")))++ describe "Statement" $ do+ describe "Declaration" $ do+ it "parses scalar declaration with nonstandard kind param (non-CHAR)" $ do+ let stStr = "integer x*8"+ expected = StDeclaration () u typeSpec Nothing decls+ typeSpec = TypeSpec () u TypeInteger Nothing+ decls = AList () u+ [ declVariable () u (varGen "x") (Just (intGen 8)) Nothing ]+ sParser stStr `shouldBe'` expected++ it "parses array declaration with nonstandard kind param (non-CHAR)" $ do+ let stStr = "integer x(2)*8"+ expected = StDeclaration () u typeSpec Nothing decls+ typeSpec = TypeSpec () u TypeInteger Nothing+ decls = AList () u+ [ declArray () u (varGen "x") dims (Just (intGen 8)) Nothing ]+ dims = AList () u+ [ DimensionDeclarator () u Nothing (Just (intGen 2)) ]+ sParser stStr `shouldBe'` expected++ it "parses array declaration with nonstandard kind param (non-CHAR) and nonstandard dimension/charlen order" $ do+ let stStr = "integer x*8(2)"+ expected = StDeclaration () u typeSpec Nothing decls+ typeSpec = TypeSpec () u TypeInteger Nothing+ decls = AList () u+ [ declArray () u (varGen "x") dims (Just (intGen 8)) Nothing ]+ dims = AList () u+ [ DimensionDeclarator () u Nothing (Just (intGen 2)) ]+ sParser stStr `shouldBe'` expected++ describe "Function call" $ do+ it "parses a simple function call" $ do+ let stStr = "call double(i, i)"+ expected = StCall () u (varGen "double") (Just args)+ args = AList () u [arg, arg]+ arg = Argument () u Nothing (ArgExpr (varGen "i"))+ sParser stStr `shouldBe'` expected++ it "parses a parenthesized variable as a special indirect/copied variable reference" $ do+ let stStr = "call double((i), i)"+ expected = StCall () u (varGen "double") (Just args)+ args = AList () u [ genArg (ArgExprVar () u "i")+ , genArg (ArgExpr (varGen "i")) ]+ genArg = Argument () u Nothing+ sParser stStr `shouldBe'` expected
+ test/Language/Fortran/Parser/Free/Fortran2003Spec.hs view
@@ -0,0 +1,176 @@+module Language.Fortran.Parser.Free.Fortran2003Spec ( spec ) where++import Prelude hiding (GT, EQ, exp, pred)++import Test.Hspec+import TestUtil+import Language.Fortran.Parser.Free.Common++import Language.Fortran.AST+import Language.Fortran.Version+import Language.Fortran.Parser+import Language.Fortran.Parser.Monad ( Parse )+import qualified Language.Fortran.Parser.Free.Fortran2003 as F2003+import qualified Language.Fortran.Parser.Free.Lexer as Free++import qualified Data.ByteString.Char8 as B++parseWith :: Parse Free.AlexInput Free.Token a -> String -> a+parseWith p = parseUnsafe (makeParserFree p Fortran2003) . B.pack++eParser :: String -> Expression ()+eParser = parseUnsafe p . B.pack+ where p = makeParser initParseStateFreeExpr F2003.expressionParser Fortran2003++sParser :: String -> Statement ()+sParser = parseWith F2003.statementParser++bParser :: String -> Block ()+bParser = parseWith F2003.blockParser++fParser :: String -> ProgramUnit ()+fParser = parseWith F2003.functionParser++spec :: Spec+spec =+ describe "Fortran 2003 Parser" $ do+ describe "Modules" $ do+ it "parses use statement, intrinsic module" $ do+ let renames = fromList ()+ [ UseRename () u (varGen "sprod") (varGen "prod")+ , UseRename () u (varGen "a") (varGen "b") ]+ st = StUse () u (varGen "mod") (Just ModIntrinsic) Permissive (Just renames)+ sParser "use, intrinsic :: mod, sprod => prod, a => b" `shouldBe'` st++ it "parses use statement, non_intrinsic module" $ do+ let renames = fromList ()+ [ UseRename () u (varGen "sprod") (varGen "prod")+ , UseRename () u (varGen "a") (varGen "b") ]+ st = StUse () u (varGen "mod") (Just ModNonIntrinsic) Exclusive (Just renames)+ sParser "use, non_intrinsic :: mod, only: sprod => prod, a => b" `shouldBe'` st++ it "parses use statement, unspecified nature of module" $ do+ let renames = fromList ()+ [ UseRename () u (varGen "sprod") (varGen "prod")+ , UseRename () u (varGen "a") (varGen "b") ]+ st = StUse () u (varGen "mod") Nothing Permissive (Just renames)+ sParser "use :: mod, sprod => prod, a => b" `shouldBe'` st++ it "parses procedure (interface-name, attribute, proc-decl)" $ do+ let call = ExpFunctionCall () u (varGen "c") Nothing+ st = StProcedure () u (Just (ProcInterfaceName () u (varGen "a")))+ (Just (AttrSave () u))+ (AList () u [ProcDecl () u (varGen "b") (Just call)])+ sParser "PROCEDURE(a), SAVE :: b => c()" `shouldBe'` st++ it "parses procedure (class-star, bind-name, proc-decls)" $ do+ let call = ExpFunctionCall () u (varGen "c") Nothing+ clas = TypeSpec () u ClassStar Nothing+ st = StProcedure () u (Just (ProcInterfaceType () u clas))+ (Just (AttrSuffix () u (SfxBind () u (Just (ExpValue () u (ValString "e"))))))+ (AList () u [ProcDecl () u (varGen "b") (Just call)+ ,ProcDecl () u (varGen "d") (Just call)])+ sParser "PROCEDURE(CLASS(*)), BIND(C, NAME=\"e\") :: b => c(), d => c()" `shouldBe'` st++ it "parses procedure (class-custom, bind, proc-decls)" $ do+ let call = ExpFunctionCall () u (varGen "c") Nothing+ clas = TypeSpec () u (ClassCustom "e") Nothing+ st = StProcedure () u (Just (ProcInterfaceType () u clas))+ (Just (AttrSuffix () u (SfxBind () u Nothing)))+ (AList () u [ProcDecl () u (varGen "b") (Just call)+ ,ProcDecl () u (varGen "d") (Just call)])+ sParser "PROCEDURE(CLASS(e)), BIND(C) :: b => c(), d => c()" `shouldBe'` st++ it "import statements" $ do+ let st = StImport () u (AList () u [varGen "a", varGen "b"])+ sParser "import a, b" `shouldBe'` st+ sParser "import :: a, b" `shouldBe'` st++ it "parses function with bind" $ do+ let puFunction = PUFunction () u+ fType = Nothing+ fPre = emptyPrefixes+ fSuf = fromList' () [SfxBind () u (Just $ ExpValue () u (ValString "f"))]+ fName = "f"+ fArgs = Nothing+ fRes = Nothing+ fBody = []+ fSub = Nothing+ fStr = init $ unlines ["function f() bind(c,name=\"f\")"+ , "end function f" ]+ let expected = puFunction fType (fPre, fSuf) fName fArgs fRes fBody fSub+ fParser fStr `shouldBe'` expected++ it "parses asynchronous decl" $ do+ let decls = [declVarGen "a", declVarGen "b"]+ st = StAsynchronous () u (AList () u decls)+ sParser "asynchronous a, b" `shouldBe'` st+ sParser "asynchronous :: a, b" `shouldBe'` st++ it "parses asynchronous attribute" $ do+ let decls = [declVarGen "a", declVarGen "b"]+ ty = TypeSpec () u TypeInteger Nothing+ attrs = [AttrAsynchronous () u]+ st = StDeclaration () u ty (Just (AList () u attrs)) (AList () u decls)+ sParser "integer, asynchronous :: a, b" `shouldBe'` st++ it "parses enumerators" $ do+ let decls = [ declVariable () u (varGen "a") Nothing (Just (intGen 1))+ , declVariable () u (varGen "b") Nothing Nothing ]+ st = StEnumerator () u (AList () u decls)+ sParser "enum, bind(c)" `shouldBe'` StEnum () u+ sParser "enumerator :: a = 1, b" `shouldBe'` st+ sParser "end enum" `shouldBe'` StEndEnum () u++ it "parses allocate with type_spec" $ do+ let sel = Selector () u (Just (ExpValue () u ValColon)) (Just (varGen "foo"))+ ty = TypeSpec () u TypeCharacter (Just sel)+ decls = AList () u [declVarGen "s"]+ st = StDeclaration () u ty (Just (AList () u [AttrAllocatable () u])) decls+ sParser "character(len=:,kind=foo), allocatable :: s" `shouldBe'` st++ it "parses allocate with type_spec" $ do+ let sel = Selector () u (Just (intGen 3)) (Just (varGen "foo"))+ ty = TypeSpec () u TypeCharacter (Just sel)+ st = StAllocate () u (Just ty) (AList () u [varGen "s"]) Nothing+ sParser "allocate(character(len=3,kind=foo) :: s)" `shouldBe'` st++ it "parses protected" $ do+ let ty = TypeSpec () u TypeReal Nothing+ decls = AList () u [declVarGen "x"]+ st1 = StDeclaration () u ty (Just (AList () u [AttrProtected () u, AttrPublic () u])) decls+ st2 = StProtected () u (Just (AList () u [varGen "x"]))+ sParser "real, protected, public :: x" `shouldBe'` st1+ sParser "protected x" `shouldBe'` st2++ describe "labelled where" $ do+ it "parses where construct statement" $+ sParser "foo: where (.true.)" `shouldBe'` StWhereConstruct () u (Just "foo") valTrue++ it "parses elsewhere statement" $+ sParser "elsewhere ab101" `shouldBe'` StElsewhere () u (Just "ab101") Nothing++ it "parses elsewhere statement" $ do+ let exp = ExpBinary () u GT (varGen "a") (varGen "b")+ sParser "elsewhere (a > b) A123" `shouldBe'` StElsewhere () u (Just "a123") (Just exp)++ it "parses endwhere statement" $+ sParser "endwhere foo1" `shouldBe'` StEndWhere () u (Just "foo1")++ describe "associate block" $ do+ it "parses multiple assignment associate block" $ do+ let text = unlines [ "associate (x => a, y => (a * b))"+ , " print *, x"+ , " print *, y"+ , "end associate" ]+ expected = BlAssociate () u Nothing Nothing abbrevs body' Nothing+ body' = [blStmtPrint "x", blStmtPrint "y"]+ blStmtPrint x = BlStatement () u Nothing (stmtPrint x)+ stmtPrint x = StPrint () u starVal (Just $ AList () u [ varGen x ])+ abbrevs = AList () u [abbrev "x" (expValVar "a"), abbrev "y" (expBinVars Multiplication "a" "b")]+ abbrev var expr = ATuple () u (expValVar var) expr+ expValVar x = ExpValue () u (ValVariable x)+ expBinVars op x1 x2 = ExpBinary () u op (expValVar x1) (expValVar x2)+ bParser text `shouldBe'` expected++ specFreeCommon sParser eParser
+ test/Language/Fortran/Parser/Free/Fortran2008Spec.hs view
@@ -0,0 +1,8 @@+module Language.Fortran.Parser.Free.Fortran2008Spec ( spec ) where++import Test.Hspec++spec :: Spec+spec =+ describe "Fortran 2008 Parser" $+ it "TODO" pending
+ test/Language/Fortran/Parser/Free/Fortran90Spec.hs view
@@ -0,0 +1,586 @@+module Language.Fortran.Parser.Free.Fortran90Spec ( spec ) where++import Prelude hiding (GT, exp, pred)++import Test.Hspec+import TestUtil+import Language.Fortran.Parser.Free.Common++import Language.Fortran.AST+import Language.Fortran.Version+import Language.Fortran.Parser+import Language.Fortran.Parser.Monad ( Parse )+import qualified Language.Fortran.Parser.Free.Fortran90 as F90+import qualified Language.Fortran.Parser.Free.Lexer as Free++--import qualified Data.List as List+import qualified Data.ByteString.Char8 as B++parseWith :: Parse Free.AlexInput Free.Token a -> String -> a+parseWith p = parseUnsafe (makeParserFree p Fortran90) . B.pack++eParser :: String -> Expression ()+eParser = parseUnsafe p . B.pack+ where p = makeParser initParseStateFreeExpr F90.expressionParser Fortran90++sParser :: String -> Statement ()+sParser = parseWith F90.statementParser++bParser :: String -> Block ()+bParser = parseWith F90.blockParser++fParser :: String -> ProgramUnit ()+fParser = parseWith F90.functionParser++{- Useful for parser debugging; Lexes the given source code.+fTok :: String -> [Token]+fTok sourceCode = collectFreeTokens Fortran95 $ B.pack sourceCode+-}++{-+ - Given a list of values, find every combination of those values:+ - combination [1,2] = [[], [1], [2], [1,2], [2,1]]+ -}+--combination :: [a] -> [[a]]+--combination = foldr ((++) . List.permutations) [] . List.subsequences++spec :: Spec+spec =+ describe "Fortran 90 Parser" $ do+ describe "Function" $ do+ let puFunction = PUFunction () u+ fType = Nothing+ fPre = emptyPrefixes+ fPreR = Just $ AList () u [PfxRecursive () u]+ fSuf = emptySuffixes+ fPreSuf = (fPre, fSuf)+ fName = "f"+ fArgs = Nothing+ fRes = Nothing+ fBody = []+ fSub = Nothing++ describe "End" $ do+ it "parses simple functions ending with \"end function [function name]\"" $ do+ let expected = puFunction fType fPreSuf fName fArgs fRes fBody fSub+ fStr = init $ unlines ["function f()"+ , "end function f" ]+ fParser fStr `shouldBe'` expected++ it "parses simple functions ending with \"end\"" $ do+ let expected = puFunction fType fPreSuf fName fArgs fRes fBody fSub+ fStr = init $ unlines ["function f()"+ , "end" ]+ fParser fStr `shouldBe'` expected++ it "parses simple functions ending with \"end function\"" $ do+ let expected = puFunction fType fPreSuf fName fArgs fRes fBody fSub+ fStr = init $ unlines ["function f()"+ , "end function" ]+ fParser fStr `shouldBe'` expected+++ it "parses functions with return type specs" $ do+ let fType' = Just $ TypeSpec () u TypeInteger Nothing+ expected = puFunction fType' fPreSuf fName fArgs fRes fBody fSub+ fStr = init $ unlines ["integer function f()"+ , "end function f" ]+ fParser fStr `shouldBe'` expected++ it "parses recursive functions" $+ let expected = puFunction fType (fPreR, fSuf) fName fArgs fRes fBody fSub+ fStr = init $ unlines ["recursive function f()", "end"]+ in fParser fStr `shouldBe'` expected+++ it "parses functions with a list of arguments" $+ let fArgs' = Just $ AList () u [ varGen "x", varGen "y", varGen "z" ]+ expected = puFunction fType fPreSuf fName fArgs' fRes fBody fSub+ fStr = init $ unlines ["function f(x, y, z)"+ , "end function f" ]+ in fParser fStr `shouldBe'` expected++ it "parses functions with a result variable" $+ let fRes' = Just $ varGen "i"+ expected = puFunction fType fPreSuf fName fArgs fRes' fBody fSub+ fStr = init $ unlines ["function f() result(i)"+ , "end function f" ]+ in fParser fStr `shouldBe'` expected++ it "parses functions with function bodies" $+ let decrementRHS = ExpBinary () u Subtraction (varGen "i") (intGen 1)+ f1 = StPrint () u starVal (Just $ AList () u [ varGen "i" ])+ f2 = StExpressionAssign () u (varGen "i") decrementRHS+ fBody' = [ BlStatement () u Nothing f1 , BlStatement () u Nothing f2 ]+ expected = puFunction fType fPreSuf fName fArgs fRes fBody' fSub+ fStr = init $ unlines ["function f()"+ , " print *, i"+ , " i = (i - 1)"+ , "end function f" ]+ in fParser fStr `shouldBe'` expected++ it "parses complex functions" $+ let fType' = Just $ TypeSpec () u TypeInteger Nothing+ fArgs' = Just $ AList () u [ varGen "x", varGen "y", varGen "z" ]+ fRes' = Just $ varGen "i"+ decrementRHS = ExpBinary () u Subtraction (varGen "i") (intGen 1)+ f1 = StPrint () u starVal (Just $ AList () u [ varGen "i" ])+ f2 = StExpressionAssign () u (varGen "i") decrementRHS+ fBody' = [ BlStatement () u Nothing f1 , BlStatement () u Nothing f2 ]+ expected = puFunction fType' fPreSuf fName fArgs' fRes' fBody' fSub+ fStr = init $ unlines [ "integer function f(x, y, z) result(i)"+ , " print *, i"+ , " i = (i - 1)"+ , "end function f" ]+ in fParser fStr `shouldBe'` expected++ describe "Expression" $ do+ it "parses logical literal without kind parameter" $ do+ eParser ".true." `shouldBe'` valTrue++ it "parses logical literal with kind parameter" $ do+ let kp = ExpValue () u (ValVariable "kind")+ eParser ".false._kind" `shouldBe'` valFalse' kp++ it "parses array initialisation exp" $ do+ let list = AList () u [ intGen 1, intGen 2, intGen 3, intGen 4 ]+ eParser "(/ 1, 2, 3, 4 /)" `shouldBe'` ExpInitialisation () u list++ describe "Custom operator" $ do+ let unOp = UnCustom ".inverse."+ unExp = ExpUnary () u unOp $ intGen 42++ it "parses unary custom operator" $+ eParser ".inverse. 42" `shouldBe'` unExp++ let binOp = BinCustom ".xor."+ it "parses binary custom operator" $ do+ let expected = ExpBinary () u binOp (intGen 24) (intGen 42)+ eParser "24 .xor. 42" `shouldBe'` expected++ it "parses mixed unary custom operator" $ do+ let binExp = ExpBinary () u binOp unExp (intGen 24)+ eParser ".inverse. 42 .xor. 24" `shouldBe'` binExp++ it "parses data ref" $ do+ let range = fromList () [ IxSingle () u Nothing $ intGen 10 ]+ sub = ExpSubscript () u (varGen "y") range+ innerRefExp = ExpDataRef () u (varGen "x") sub+ exp = ExpDataRef () u innerRefExp (varGen "z")+ eParser "x % y(10) % z" `shouldBe'` exp++ it "parses section subscript" $ do+ let range = [ IxSingle () u Nothing $ intGen 10+ , IxRange () u Nothing (Just $ intGen 1) (Just $ intGen 2)+ , IxSingle () u Nothing $ varGen "y" ]+ exp = ExpSubscript () u (varGen "x") (fromList () range)+ eParser "x (10, : 1 : 2, y)" `shouldBe'` exp++ describe "Statement" $ do+ it "data ref assignment" $ do+ let indicies = AList () u [ IxSingle () u Nothing (intGen 1) ]+ subs = ExpSubscript () u (varGen "x") indicies+ lhs = ExpDataRef () u subs (varGen "y")+ st = StExpressionAssign () u lhs (intGen 1)+ sParser "x(1) % y = 1" `shouldBe'` st++ it "parses pause statements" $ do+ let stPause = StPause () u Nothing+ stStr = "PAUSE"+ sParser stStr `shouldBe'` stPause++ it "parses pause statements with expression" $ do+ let stPause = StPause () u (Just (strGen "MESSAGE"))+ stStr = "PAUSE \"MESSAGE\""+ sParser stStr `shouldBe'` stPause++ it "parses declaration with attributes" $ do+ let typeSpec = TypeSpec () u TypeReal Nothing+ attrs = AList () u [ AttrExternal () u+ , AttrIntent () u Out+ , AttrDimension () u $ AList () u+ [ DimensionDeclarator () u+ (Just $ intGen 3) (Just $ intGen 10)+ ]+ ]+ declarators = AList () u [ declVarGen "x", declVarGen "y"]+ expected = StDeclaration () u typeSpec (Just attrs) declarators+ stStr = "real, external, intent (out), dimension (3:10) :: x, y"+ sParser stStr `shouldBe'` expected++ it "parses declaration with old syntax" $ do+ let typeSpec = TypeSpec () u TypeLogical Nothing+ declarators = AList () u [ declVarGen "x", declVarGen "y"]+ expected = StDeclaration () u typeSpec Nothing declarators+ stStr = "logical x, y"+ sParser stStr `shouldBe'` expected++ it "parses declaration with initialisation" $+ let typeSpec = TypeSpec () u TypeComplex Nothing+ init' = ExpValue () u (ValComplex (intGen 24) (realGen (42.0::Double)))+ declarators = AList () u+ [ declVariable () u (varGen "x") Nothing (Just init') ]+ expected = StDeclaration () u typeSpec Nothing declarators+ stStr = "complex :: x = (24, 42.0)"+ in sParser stStr `shouldBe'` expected++ it "parses declaration of custom type" $ do+ let typeSpec = TypeSpec () u (TypeCustom "meinetype") Nothing+ declarators = AList () u [declVarGen "x"]+ expected = StDeclaration () u typeSpec Nothing declarators+ stStr = "type (MeineType) :: x"+ sParser stStr `shouldBe'` expected++ it "parses declaration type with kind selector" $ do+ let selector = Selector () u Nothing (Just $ varGen "hello")+ typeSpec = TypeSpec () u TypeInteger (Just selector)+ declarators = AList () u [declVarGen "x"]+ expected = StDeclaration () u typeSpec Nothing declarators+ stStr = "integer (hello) :: x"+ sParser stStr `shouldBe'` expected++ it "parses intent statement" $ do+ let stStr = "intent (inout) :: a"+ expected = StIntent () u InOut (fromList () [ varGen "a" ])+ sParser stStr `shouldBe'` expected++ it "parses optional statement" $ do+ let stStr = "optional x"+ expected = StOptional () u (fromList () [ varGen "x" ])+ sParser stStr `shouldBe'` expected++ it "parses public statement" $ do+ let stStr = "public :: x"+ expected = StPublic () u (Just $ fromList () [ varGen "x" ])+ sParser stStr `shouldBe'` expected++ it "parses public assignment" $ do+ let expected = StPublic () u (Just $ fromList () [ assVal ])+ sParser "public :: assignment (=)" `shouldBe'` expected++ it "parses private statement" $+ sParser "private" `shouldBe'` StPrivate () u Nothing++ it "parses private operator" $ do+ let expected = StPrivate () u (Just $ fromList () [ opGen "*" ])+ sParser "private operator ( * )" `shouldBe'` expected++ it "parses save statement" $ do+ let list = [ varGen "hello", varGen "bye" ]+ expected = StSave () u (Just $ fromList () list)+ stStr = "save /hello/, bye"+ sParser stStr `shouldBe'` expected++ it "parses parameter statement" $ do+ let ass1 = declVariable () u (varGen "x") Nothing (Just $ intGen 10)+ ass2 = declVariable () u (varGen "y") Nothing (Just $ intGen 20)+ expected = StParameter () u (fromList () [ ass1, ass2 ])+ sParser "parameter (x = 10, y = 20)" `shouldBe'` expected++ describe "Implicit" $ do+ it "parses implicit none" $ do+ let st = StImplicit () u Nothing+ sParser "implicit none" `shouldBe'` st++ it "parses implicit with single" $ do+ let typeSpec = TypeSpec () u TypeCharacter Nothing+ impEls = [ ImpCharacter () u "k" ]+ impLists = [ ImpList () u typeSpec (fromList () impEls) ]+ st = StImplicit () u (Just $ fromList () impLists)+ sParser "implicit character (k)" `shouldBe'` st++ it "parses implicit with range" $ do+ let typeSpec = TypeSpec () u TypeLogical Nothing+ impEls = [ ImpRange () u "x" "z" ]+ impLists = [ ImpList () u typeSpec (fromList () impEls) ]+ st = StImplicit () u (Just $ fromList () impLists)+ sParser "implicit logical (x-z)" `shouldBe'` st++ it "parses implicit statement" $ do+ let typeSpec1 = TypeSpec () u TypeCharacter Nothing+ typeSpec2 = TypeSpec () u TypeInteger Nothing+ impEls1 = [ ImpCharacter () u "s", ImpCharacter () u "a" ]+ impEls2 = [ ImpRange () u "x" "z" ]+ impLists = [ ImpList () u typeSpec1 (fromList () impEls1)+ , ImpList () u typeSpec2 (fromList () impEls2) ]+ st = StImplicit () u (Just $ fromList () impLists)+ sParser "implicit character (s, a), integer (x-z)" `shouldBe'` st++ describe "Data" $ do+ it "parses vanilla" $ do+ let nlist = fromList () [ varGen "x", varGen "y" ]+ vlist = fromList () [ intGen 1, intGen 2 ]+ list = [ DataGroup () u nlist vlist ]+ expected = StData () u (fromList () list)+ stStr = "data x,y/1,2/"+ sParser stStr `shouldBe'` expected++ describe "Delimeter" $ do+ let [ nlist1, vlist1 ] =+ map (fromList () . return) [ varGen "x", intGen 1 ]+ [ nlist2, vlist2 ] =+ map (fromList () . return) [ varGen "y", intGen 2 ]+ list = [ DataGroup () u nlist1 vlist1+ , DataGroup () u nlist2 vlist2 ]+ expected = StData () u (fromList () list)++ it "parses comma delimited init groups" $+ sParser "data x/1/, y/2/" `shouldBe'` expected++ it "parses non-comma delimited init groups" $+ sParser "data x/1/ y/2/" `shouldBe'` expected++ describe "Namelist" $ do+ let groupNames = [ ExpValue () u (ValVariable "something")+ , ExpValue () u (ValVariable "other") ]+ itemss = [ fromList () [ varGen "a", varGen "b", varGen "c" ]+ , fromList () [ varGen "y" ] ]+ st = StNamelist () u $+ fromList () [ Namelist () u (head groupNames) (head itemss)+ , Namelist () u (last groupNames) (last itemss) ]++ it "parses namelist statement (comma delimited) (1)" $+ sParser "namelist /something/a,b,c,/other/y" `shouldBe'` st++ it "parses namelist statement (2)" $+ sParser "namelist /something/a,b,c/other/y" `shouldBe'` st++ describe "Common" $ do+ let commonNames = [ ExpValue () u (ValVariable "something")+ , ExpValue () u (ValVariable "other") ]+ itemss = [ fromList () [ declVarGen "a", declVarGen "b", declVarGen "c" ]+ , fromList () [ declVarGen "y" ] ]+ st = StCommon () u $ fromList ()+ [ CommonGroup () u Nothing (fromList () [ declVarGen "q" ])+ , CommonGroup () u (Just $ head commonNames) (head itemss)+ , CommonGroup () u (Just $ last commonNames) (last itemss) ]++ it "parses common statement (comma delimited) (1)" $+ sParser "common q /something/a,b,c, /other/y" `shouldBe'` st++ it "parses common statement (2)" $+ sParser "common q /something/a,b,c /other/y" `shouldBe'` st++ it "parses equivalence statement" $ do+ let eqALists = fromList ()+ [ fromList ()+ [ let indicies = fromList () [ IxSingle () u Nothing (intGen 1) ]+ in ExpSubscript () u (varGen "a") indicies+ , varGen "x"+ ]+ , fromList ()+ [ varGen "y"+ , varGen "z"+ , let indicies = fromList () [ IxRange () u (Just $ intGen 1)+ (Just $ intGen 42)+ Nothing ]+ in ExpSubscript () u (varGen "d") indicies+ ]+ ]+ let st = StEquivalence () u eqALists+ sParser "equivalence (a(1), x), (y, z, d(1:42))" `shouldBe'` st++ describe "Dynamic allocation" $ do+ it "parses allocate statement" $ do+ let opt = AOStat () u (varGen "a")+ allocs = fromList ()+ [ varGen "x"+ , ExpDataRef () u (varGen "st") (varGen "part")+ ]+ let s = StAllocate () u Nothing allocs (Just (AList () u [opt]))+ sParser "allocate (x, st % part, STAT = a)" `shouldBe'` s++ it "parses deallocate statement" $ do+ let opt = AOStat () u (varGen "a")+ allocs = fromList ()+ [ let indicies = fromList () [ IxSingle () u Nothing (intGen 20) ]+ in ExpSubscript () u (varGen "smt") indicies+ ]+ s = StDeallocate () u allocs Nothing+ s' = StDeallocate () u allocs (Just (AList () u [opt]))+ sParser "deallocate (smt ( 20 ))" `shouldBe'` s+ sParser "deallocate (smt ( 20 ), stat=a)" `shouldBe'` s'++ it "parses nullify statement" $ do+ let s = StNullify () u (fromList () [ varGen "x" ])+ sParser "nullify (x)" `shouldBe'` s++ it "parses pointer assignment" $ do+ let src = ExpDataRef () u (varGen "x") (varGen "y")+ st = StPointerAssign () u src (varGen "exp")+ sParser "x % y => exp" `shouldBe'` st++ describe "Where" $ do+ it "parses where statement" $ do+ let exp = ExpBinary () u Subtraction (varGen "temp") (varGen "r_temp")+ pred = ExpBinary () u GT (varGen "temp") (intGen 100)+ assignment = StExpressionAssign () u (varGen "temp") exp+ st = StWhere () u pred assignment+ sParser "where (temp > 100) temp = temp - r_temp"`shouldBe'` st++ describe "Where block" $ do+ it "parses where construct statement" $+ sParser "where (.true.)" `shouldBe'` StWhereConstruct () u Nothing valTrue++ it "parses elsewhere statement" $+ sParser "elsewhere" `shouldBe'` StElsewhere () u Nothing Nothing++ it "parses elsewhere statement" $ do+ let exp = ExpBinary () u GT (varGen "a") (varGen "b")+ sParser "elsewhere (a > b)" `shouldBe'` StElsewhere () u Nothing (Just exp)++ it "parses endwhere statement" $+ sParser "endwhere" `shouldBe'` StEndWhere () u Nothing++ describe "If" $ do+ let stPrint = StPrint () u starVal (Just $ fromList () [ ExpValue () u (ValString "foo")])+ it "parser if block" $+ let ifBlockSrc = unlines [ "if (.false.) then", "print *, 'foo'", "end if"]+ in bParser ifBlockSrc `shouldBe'` BlIf () u Nothing Nothing [Just valFalse] [[BlStatement () u Nothing stPrint]] Nothing++ it "parses named if block" $ do+ let ifBlockSrc = unlines [ "mylabel : if (.true.) then", "print *, 'foo'", "end if mylabel"]+ ifBlock = BlIf () u Nothing (Just "mylabel") [Just valTrue] [[BlStatement () u Nothing stPrint]] Nothing+ bParser ifBlockSrc `shouldBe'` ifBlock++ it "parses if-else block with inline comments (stripped)" $+ let ifBlockSrc = unlines [ "if (.false.) then ! comment if", "print *, 'foo'", "else ! comment else", "print *, 'foo'", "end if ! comment end"]+ in bParser ifBlockSrc `shouldBe'` BlIf () u Nothing Nothing [Just valFalse, Nothing] [[BlStatement () u Nothing stPrint], [BlStatement () u Nothing stPrint]] Nothing++ it "parses logical if statement" $ do+ let assignment = StExpressionAssign () u (varGen "a") (varGen "b")+ stIf = StIfLogical () u valTrue assignment+ sParser "if (.true.) a = b" `shouldBe'` stIf++ it "parses arithmetic if statement" $ do+ let stIf = StIfArithmetic () u (varGen "x") (intGen 1)+ (intGen 2)+ (intGen 3)+ sParser "if (x) 1, 2, 3" `shouldBe'` stIf++ describe "Case" $ do+ let printArgs str = Just $ AList () u [ExpValue () u $ ValString str]+ printStmt = StPrint () u (ExpValue () u ValStar) . printArgs+ printBlock = BlStatement () u Nothing . printStmt+ ind2 = AList () u . pure $ IxSingle () u Nothing $ intGen 2+ ind3Plus = AList () u . pure $ IxRange () u (Just $ intGen 3) Nothing Nothing+ conds = [Just ind2, Just ind3Plus, Nothing]+ it "unlabelled case block (with inline comments to be stripped)" $ do+ let src = unlines [ "select case (x) ! comment select"+ , "! full line before first case (unrepresentable)"+ , "case (2) ! comment case 1"+ , "print *, 'foo'"+ , "case (3:) ! comment case 2"+ , "print *, 'bar'"+ , "case default ! comment case 3"+ , "print *, 'baz'"+ , "end select ! comment end"+ ]+ blocks = (fmap . fmap) printBlock [["foo"], ["bar"], ["baz"]]+ block = BlCase () u Nothing Nothing (varGen "x") conds blocks Nothing+ bParser src `shouldBe'` block+ it "labelled case block (with inline comments to be stripped" $ do+ let src = unlines [ "10 mylabel: select case (x) ! comment select"+ , "20 case (2) ! comment case 1"+ , "30 print *, 'foo'"+ , "40 case (3:) ! comment case 2"+ , "50 print *, 'bar'"+ , "60 case default ! comment case 3"+ , "70 print *, 'baz'"+ , "80 end select mylabel ! comment end"+ ]+ blocks = (fmap . fmap)+ (\(label, arg) -> BlStatement () u (Just $ intGen label) $ printStmt arg)+ [[(30, "foo")], [(50, "bar")], [(70, "baz")]]+ block = BlCase () u+ (Just $ intGen 10) (Just "mylabel") (varGen "x")+ conds blocks+ (Just $ intGen 80)+ bParser src `shouldBe'` block++ describe "Do" $ do+ it "parses do statement with label" $ do+ let assign = StExpressionAssign () u (varGen "i") (intGen 0)+ doSpec = DoSpecification () u assign (intGen 42) Nothing+ st = StDo () u Nothing (Just $ intGen 24) (Just doSpec)+ sParser "do 24, i = 0, 42" `shouldBe'` st++ it "parses do statement without label" $ do+ let assign = StExpressionAssign () u (varGen "i") (intGen 0)+ doSpec = DoSpecification () u assign (intGen 42) Nothing+ st = StDo () u Nothing Nothing (Just doSpec)+ sParser "do i = 0, 42" `shouldBe'` st++ it "parses infinite do" $ do+ let st = StDo () u Nothing Nothing Nothing+ sParser "do" `shouldBe'` st++ it "parses end do statement" $ do+ let st = StEnddo () u (Just "constructor")+ sParser "end do constructor" `shouldBe'` st++ describe "DO WHILE" $ do+ it "parses unnamed do while statement" $ do+ let st = StDoWhile () u Nothing Nothing valTrue+ sParser "do while (.true.)" `shouldBe'` st++ it "parses named do while statement" $ do+ let st = StDoWhile () u (Just "name") Nothing valTrue+ sParser "name: do while (.true.)" `shouldBe'` st++ it "parses unnamed labelled do while statement" $ do+ let st = StDoWhile () u Nothing (Just (intGen 999)) valTrue+ sParser "do 999 while (.true.)" `shouldBe'` st++ describe "Goto" $ do+ it "parses vanilla goto" $ do+ let st = StGotoUnconditional () u (intGen 999)+ sParser "goto 999" `shouldBe'` st++ it "parses computed goto" $ do+ let list = fromList () [ intGen 10, intGen 20, intGen 30 ]+ st = StGotoComputed () u list (intGen 20)+ sParser "goto (10, 20, 30) 20" `shouldBe'` st++ it "parses assigned goto" $ do+ let list = fromList () [ intGen 10, intGen 20, intGen 30 ]+ st = StGotoAssigned () u (varGen "i") (Just list)+ sParser "goto i, (10, 20, 30)" `shouldBe'` st++ it "parses label assignment" $ do+ let st = StLabelAssign () u (intGen 20) (varGen "l")+ sParser "assign 20 to l" `shouldBe'` st++ describe "IO" $ do+ it "parses vanilla print" $ do+ let st = StPrint () u starVal (Just $ fromList () [ varGen "hex" ])+ sParser "print *, hex" `shouldBe'` st++ it "parses write with implied do" $ do+ let cp1 = ControlPair () u Nothing (intGen 10)+ cp2 = ControlPair () u (Just "format") (varGen "x")+ ciList = fromList () [ cp1, cp2 ]+ assign = StExpressionAssign () u (varGen "i") (intGen 1)+ doSpec = DoSpecification () u assign (intGen 42) (Just $ intGen 2)+ alist = fromList () [ varGen "i", varGen "j" ]+ outList = fromList () [ ExpImpliedDo () u alist doSpec ]+ st = StWrite () u ciList (Just outList)+ sParser "write (10, FORMAT = x) (i, j, i = 1, 42, 2)" `shouldBe'` st++ it "parses use statement with renames" $ do+ let renames = fromList ()+ [ UseRename () u (varGen "sprod") (varGen "prod")+ , UseRename () u (varGen "a") (varGen "b") ]+ st = StUse () u (varGen "stats_lib") Nothing Permissive (Just renames)+ sParser "use stats_lib, sprod => prod, a => b" `shouldBe'` st++ it "parses use statement with only list" $ do+ let onlys = fromList ()+ [ UseID () u (varGen "a")+ , UseRename () u (varGen "b") (varGen "c")+ , UseID () u (ExpValue () u (ValOperator "+"))+ , UseID () u (ExpValue () u ValAssignment) ]+ st = StUse () u (varGen "stats_lib") Nothing Exclusive (Just onlys)+ sParser "use stats_lib, only: a, b => c, operator(+), assignment(=)" `shouldBe'` st++ specFreeCommon sParser eParser
+ test/Language/Fortran/Parser/Free/Fortran95Spec.hs view
@@ -0,0 +1,655 @@+module Language.Fortran.Parser.Free.Fortran95Spec ( spec ) where++import Prelude hiding (GT, EQ, exp, pred)++import Test.Hspec+import TestUtil+import Language.Fortran.Parser.Free.Common++import Language.Fortran.AST+import Language.Fortran.Version+import Language.Fortran.Parser+import Language.Fortran.Parser.Monad ( Parse )+import qualified Language.Fortran.Parser.Free.Fortran95 as F95+import qualified Language.Fortran.Parser.Free.Lexer as Free++import qualified Data.List as List+import Data.Foldable(forM_)+import qualified Data.ByteString.Char8 as B+import Control.Exception (evaluate)++parseWith :: Parse Free.AlexInput Free.Token a -> String -> a+parseWith p = parseUnsafe (makeParserFree p Fortran95) . B.pack++eParser :: String -> Expression ()+eParser = parseUnsafe p . B.pack+ where p = makeParser initParseStateFreeExpr F95.expressionParser Fortran95++sParser :: String -> Statement ()+sParser = parseWith F95.statementParser++bParser :: String -> Block ()+bParser = parseWith F95.blockParser++fParser :: String -> ProgramUnit ()+fParser = parseWith F95.functionParser++{- Useful for parser debugging; Lexes the given source code.+fTok :: String -> [Token]+fTok sourceCode = collectFreeTokens Fortran95 $ B.pack sourceCode+-}++{-+ - Given a list of values, find every combination of those values:+ - combination [1,2] = [[], [1], [2], [1,2], [2,1]]+ -}+combination :: [a] -> [[a]]+combination = foldr ((++) . List.permutations) [] . List.subsequences++spec :: Spec+spec =+ describe "Fortran 95 Parser" $ do+ describe "Function" $ do+ let puFunction = PUFunction () u+ fType = Nothing+ fSuf = emptySuffixes+ fPreSuf = emptyPrefixSuffix+ fName = "f"+ fArgs = Nothing+ fRes = Nothing+ fBody = []+ fSub = Nothing++ describe "End" $ do+ it "parses simple functions ending with \"end function [function name]\"" $ do+ let expected = puFunction fType fPreSuf fName fArgs fRes fBody fSub+ fStr = init $ unlines ["function f()"+ , "end function f" ]+ fParser fStr `shouldBe'` expected++ it "parses simple functions ending with \"end\"" $ do+ let expected = puFunction fType fPreSuf fName fArgs fRes fBody fSub+ fStr = init $ unlines ["function f()"+ , "end" ]+ fParser fStr `shouldBe'` expected++ it "parses simple functions ending with \"end function\"" $ do+ let expected = puFunction fType fPreSuf fName fArgs fRes fBody fSub+ fStr = init $ unlines ["function f()"+ , "end function" ]+ fParser fStr `shouldBe'` expected+++ it "parses functions with return type specs" $ do+ let fType' = Just $ TypeSpec () u TypeInteger Nothing+ expected = puFunction fType' fPreSuf fName fArgs fRes fBody fSub+ fStr = init $ unlines ["integer function f()"+ , "end function f" ]+ fParser fStr `shouldBe'` expected++ describe "parses function options (recursive, pure, elemental)" $ do+ let options_list = map unzip $ combination+ [ ("recursive ", PfxRecursive () u)+ , ("pure ", PfxPure () u)+ , ("elemental ", PfxElemental () u) ]++ forM_ options_list (\(strs, opts) -> do+ let isElem (PfxElemental {}) = True; isElem _ = False+ isRec (PfxRecursive {}) = True; isRec _ = False+ str = concat strs+ fStr = str ++ init (unlines ["function f()", "end"])+ pfx = fromList' () opts+ --let expected = puFunction fType+ if any isElem opts && any isRec opts+ then+ it ("Shouldn't parse: " ++ show fStr ++ ": " ++ show opts) $+ evaluate (fParser fStr) `shouldThrow` anyIOException+ else+ it ("Should parse: " ++ show fStr ++ ": " ++ show opts) $ do+ let expected' = puFunction fType (pfx, fSuf) fName fArgs fRes fBody fSub+ fParser fStr `shouldBe'` expected'+ )++ it "parses functions with a list of arguments" $ do+ let fArgs' = Just $ AList () u [ varGen "x", varGen "y", varGen "z" ]+ expected = puFunction fType fPreSuf fName fArgs' fRes fBody fSub+ fStr = init $ unlines ["function f(x, y, z)"+ , "end function f" ]+ fParser fStr `shouldBe'` expected++ it "parses functions with a result variable" $ do+ let fRes' = Just $ varGen "i"+ expected = puFunction fType fPreSuf fName fArgs fRes' fBody fSub+ fStr = init $ unlines ["function f() result(i)"+ , "end function f" ]+ fParser fStr `shouldBe'` expected++ it "parses functions with function bodies" $ do+ let decrementRHS = ExpBinary () u Subtraction (varGen "i") (intGen 1)+ f1 = StPrint () u starVal (Just $ AList () u [ varGen "i" ])+ f2 = StExpressionAssign () u (varGen "i") decrementRHS+ fBody' = [ BlStatement () u Nothing f1 , BlStatement () u Nothing f2 ]+ expected = puFunction fType fPreSuf fName fArgs fRes fBody' fSub+ fStr = init $ unlines ["function f()"+ , " print *, i"+ , " i = (i - 1)"+ , "end function f" ]+ fParser fStr `shouldBe'` expected++ it "parses complex functions" $ do+ let fType' = Just $ TypeSpec () u TypeInteger Nothing+ fArgs' = Just $ AList () u [ varGen "x", varGen "y", varGen "z" ]+ fRes' = Just $ varGen "i"+ decrementRHS = ExpBinary () u Subtraction (varGen "i") (intGen 1)+ f1 = StPrint () u starVal (Just $ AList () u [ varGen "i" ])+ f2 = StExpressionAssign () u (varGen "i") decrementRHS+ fBody' = [ BlStatement () u Nothing f1 , BlStatement () u Nothing f2 ]+ expected = puFunction fType' fPreSuf fName fArgs' fRes' fBody' fSub+ fStr = init $ unlines [ "integer function f(x, y, z) result(i)"+ , " print *, i"+ , " i = (i - 1)"+ , "end function f" ]+ fParser fStr `shouldBe'` expected++ describe "Expression" $ do+ it "parses logical literal without kind parameter" $ do+ eParser ".true." `shouldBe'` valTrue++ it "parses logical literal with kind parameter" $ do+ let kp = ExpValue () u (ValVariable "kind")+ eParser ".false._kind" `shouldBe'` valFalse' kp++ it "parses array initialisation exp" $ do+ let list = AList () u [ intGen 1, intGen 2, intGen 3, intGen 4 ]+ eParser "(/ 1, 2, 3, 4 /)" `shouldBe'` ExpInitialisation () u list++ describe "Custom operator" $ do+ let unOp = UnCustom ".inverse."+ unExp = ExpUnary () u unOp $ intGen 42++ it "parses unary custom operator" $+ eParser ".inverse. 42" `shouldBe'` unExp++ let binOp = BinCustom ".xor."+ it "parses binary custom operator" $ do+ let expected = ExpBinary () u binOp (intGen 24) (intGen 42)+ eParser "24 .xor. 42" `shouldBe'` expected++ it "parses mixed unary custom operator" $ do+ let binExp = ExpBinary () u binOp unExp (intGen 24)+ eParser ".inverse. 42 .xor. 24" `shouldBe'` binExp++ it "parses data ref" $ do+ let range = fromList () [ IxSingle () u Nothing $ intGen 10 ]+ sub = ExpSubscript () u (varGen "y") range+ innerRefExp = ExpDataRef () u (varGen "x") sub+ exp = ExpDataRef () u innerRefExp (varGen "z")+ eParser "x % y(10) % z" `shouldBe'` exp++ it "parses section subscript" $ do+ let range = [ IxSingle () u Nothing $ intGen 10+ , IxRange () u Nothing (Just $ intGen 1) (Just $ intGen 2)+ , IxSingle () u Nothing $ varGen "y" ]+ exp = ExpSubscript () u (varGen "x") (fromList () range)+ eParser "x (10, : 1 : 2, y)" `shouldBe'` exp++ describe "Statement" $ do+ it "data ref assignment" $ do+ let indicies = AList () u [ IxSingle () u Nothing (intGen 1) ]+ subs = ExpSubscript () u (varGen "x") indicies+ lhs = ExpDataRef () u subs (varGen "y")+ st = StExpressionAssign () u lhs (intGen 1)+ sParser "x(1) % y = 1" `shouldBe'` st++ it "doesn't parse assign statements" $ do+ let stStr = "ASSIGN 1 \"LABEL\""+ evaluate (sParser stStr) `shouldThrow` anyIOException++ it "doesn't parse pause statements" $ do+ let stStr = "PAUSE"+ evaluate (sParser stStr) `shouldThrow` anyIOException++ it "doesn't parse pause statements with expression" $ do+ let stStr = "PAUSE \"MESSAGE\""+ evaluate (sParser stStr) `shouldThrow` anyIOException++ it "parses declaration with attributes" $ do+ let typeSpec = TypeSpec () u TypeReal Nothing+ attrs = AList () u [ AttrExternal () u+ , AttrIntent () u Out+ , AttrDimension () u $ AList () u+ [ DimensionDeclarator () u+ (Just $ intGen 3) (Just $ intGen 10)+ ]+ ]+ declarators = AList () u+ [ declVariable () u (varGen "x") Nothing Nothing+ , declVariable () u (varGen "y") Nothing Nothing ]+ expected = StDeclaration () u typeSpec (Just attrs) declarators+ stStr = "real, external, intent (out), dimension (3:10) :: x, y"+ sParser stStr `shouldBe'` expected++ it "parses declaration with old syntax" $ do+ let typeSpec = TypeSpec () u TypeLogical Nothing+ declarators = AList () u+ [ declVariable () u (varGen "x") Nothing Nothing+ , declVariable () u (varGen "y") Nothing Nothing ]+ expected = StDeclaration () u typeSpec Nothing declarators+ stStr = "logical x, y"+ sParser stStr `shouldBe'` expected++ it "parses declaration with initialisation" $ do+ let typeSpec = TypeSpec () u TypeComplex Nothing+ init' = ExpValue () u (ValComplex (intGen 24) (realGen (42.0::Double)))+ declarators = AList () u+ [ declVariable () u (varGen "x") Nothing (Just init') ]+ expected = StDeclaration () u typeSpec Nothing declarators+ stStr = "complex :: x = (24, 42.0)"+ sParser stStr `shouldBe'` expected++ it "parses declaration of custom type" $ do+ let typeSpec = TypeSpec () u (TypeCustom "meinetype") Nothing+ declarators = AList () u+ [ declVariable () u (varGen "x") Nothing Nothing ]+ expected = StDeclaration () u typeSpec Nothing declarators+ stStr = "type (MeineType) :: x"+ sParser stStr `shouldBe'` expected++ it "parses declaration type with kind selector" $ do+ let selector = Selector () u Nothing (Just $ varGen "hello")+ typeSpec = TypeSpec () u TypeInteger (Just selector)+ declarators = AList () u+ [ declVariable () u (varGen "x") Nothing Nothing ]+ expected = StDeclaration () u typeSpec Nothing declarators+ stStr = "integer (hello) :: x"+ sParser stStr `shouldBe'` expected++ it "parses intent statement" $ do+ let stStr = "intent (inout) :: a"+ expected = StIntent () u InOut (fromList () [ varGen "a" ])+ sParser stStr `shouldBe'` expected++ it "parses optional statement" $ do+ let stStr = "optional x"+ expected = StOptional () u (fromList () [ varGen "x" ])+ sParser stStr `shouldBe'` expected++ it "parses public statement" $ do+ let stStr = "public :: x"+ expected = StPublic () u (Just $ fromList () [ varGen "x" ])+ sParser stStr `shouldBe'` expected++ it "parses public assignment" $ do+ let expected = StPublic () u (Just $ fromList () [ assVal ])+ sParser "public :: assignment (=)" `shouldBe'` expected++ it "parses private statement" $+ sParser "private" `shouldBe'` StPrivate () u Nothing++ it "parses private operator" $ do+ let expected = StPrivate () u (Just $ fromList () [ opGen "*" ])+ sParser "private operator ( * )" `shouldBe'` expected++ it "parses save statement" $ do+ let list = [ varGen "hello", varGen "bye" ]+ expected = StSave () u (Just $ fromList () list)+ stStr = "save /hello/, bye"+ sParser stStr `shouldBe'` expected++ it "parses parameter statement" $ do+ let ass1 = declVariable () u (varGen "x") Nothing (Just $ intGen 10)+ ass2 = declVariable () u (varGen "y") Nothing (Just $ intGen 20)+ expected = StParameter () u (fromList () [ ass1, ass2 ])+ sParser "parameter (x = 10, y = 20)" `shouldBe'` expected++ describe "FORALL blocks" $ do+ let stride = Just $ ExpBinary () u NE (varGen "i") (intGen 2)+ tripletSpecList = [("i", intGen 1, varGen "n", stride)]++ it "parses basic FORALL blocks" $ do+ let stStr = "FORALL (I=1:N, I /= 2)"+ expected = StForall () u Nothing (ForallHeader tripletSpecList Nothing)+ sParser stStr `shouldBe'` expected++ describe "FORALL statements" $ do+ let stride = Just $ ExpBinary () u NE (varGen "i") (intGen 2)+ tripletSpecList = [("i", intGen 1, varGen "n", stride)]+ --let varI = IxSingle () u Nothing (varGen "i")+ --let expSub1 = ExpSubscript () u (varGen "a") (AList () u [varI, varI])+ --let expSub2 = ExpSubscript () u (varGen "x") (AList () u [varI])+ --let eAssign = StExpressionAssign () u expSub1 expSub2++ it "parses basic FORALL statements" $ do+ let stStr = "FORALL (I=1:N, I /= 2)" -- A(I,I) = X(I)"+ expected = StForall () u Nothing (ForallHeader tripletSpecList Nothing)-- eAssign+ sParser stStr `shouldBe'` expected++ describe "ENDFORALL statements" $ do+ it "parses FORALL end statements" $ do+ let stStr = "ENDFORALL"+ expected = StEndForall () u Nothing+ sParser stStr `shouldBe'` expected++ it "parses FORALL end statements with label" $ do+ let stStr = "ENDFORALL A"+ expected = StEndForall () u $ Just "a"+ sParser stStr `shouldBe'` expected++ describe "Implicit" $ do+ it "parses implicit none" $ do+ let st = StImplicit () u Nothing+ sParser "implicit none" `shouldBe'` st++ it "parses implicit with single" $ do+ let typeSpec = TypeSpec () u TypeCharacter Nothing+ impEls = [ ImpCharacter () u "k" ]+ impLists = [ ImpList () u typeSpec (fromList () impEls) ]+ st = StImplicit () u (Just $ fromList () impLists)+ sParser "implicit character (k)" `shouldBe'` st++ it "parses implicit with range" $ do+ let typeSpec = TypeSpec () u TypeLogical Nothing+ impEls = [ ImpRange () u "x" "z" ]+ impLists = [ ImpList () u typeSpec (fromList () impEls) ]+ st = StImplicit () u (Just $ fromList () impLists)+ sParser "implicit logical (x-z)" `shouldBe'` st++ it "parses implicit statement" $ do+ let typeSpec1 = TypeSpec () u TypeCharacter Nothing+ typeSpec2 = TypeSpec () u TypeInteger Nothing+ impEls1 = [ ImpCharacter () u "s", ImpCharacter () u "a" ]+ impEls2 = [ ImpRange () u "x" "z" ]+ impLists = [ ImpList () u typeSpec1 (fromList () impEls1)+ , ImpList () u typeSpec2 (fromList () impEls2) ]+ st = StImplicit () u (Just $ fromList () impLists)+ sParser "implicit character (s, a), integer (x-z)" `shouldBe'` st++ describe "Data" $ do+ it "parses vanilla" $ do+ let nlist = fromList () [ varGen "x", varGen "y" ]+ vlist = fromList () [ intGen 1, intGen 2 ]+ list = [ DataGroup () u nlist vlist ]+ expected = StData () u (fromList () list)+ stStr = "data x,y/1,2/"+ sParser stStr `shouldBe'` expected++ describe "Delimeter" $ do+ let [ nlist1, vlist1 ] =+ map (fromList () . return) [ varGen "x", intGen 1 ]+ [ nlist2, vlist2 ] =+ map (fromList () . return) [ varGen "y", intGen 2 ]+ list = [ DataGroup () u nlist1 vlist1+ , DataGroup () u nlist2 vlist2 ]+ expected = StData () u (fromList () list)++ it "parses comma delimited init groups" $+ sParser "data x/1/, y/2/" `shouldBe'` expected++ it "parses non-comma delimited init groups" $+ sParser "data x/1/ y/2/" `shouldBe'` expected++ describe "Namelist" $ do+ let groupNames = [ ExpValue () u (ValVariable "something")+ , ExpValue () u (ValVariable "other") ]+ itemss = [ fromList () [ varGen "a", varGen "b", varGen "c" ]+ , fromList () [ varGen "y" ] ]+ st = StNamelist () u $+ fromList () [ Namelist () u (head groupNames) (head itemss)+ , Namelist () u (last groupNames) (last itemss) ]++ it "parses namelist statement (comma delimited) (1)" $+ sParser "namelist /something/a,b,c,/other/y" `shouldBe'` st++ it "parses namelist statement (2)" $+ sParser "namelist /something/a,b,c/other/y" `shouldBe'` st++ describe "Common" $ do+ let commonNames = [ ExpValue () u (ValVariable "something")+ , ExpValue () u (ValVariable "other") ]+ itemss = [ fromList () [ declVarGen "a", declVarGen "b", declVarGen "c" ]+ , fromList () [ declVarGen "y" ] ]+ st = StCommon () u $ fromList ()+ [ CommonGroup () u Nothing (fromList () [ declVarGen "q" ])+ , CommonGroup () u (Just $ head commonNames) (head itemss)+ , CommonGroup () u (Just $ last commonNames) (last itemss) ]++ it "parses common statement (comma delimited) (1)" $+ sParser "common q /something/a,b,c, /other/y" `shouldBe'` st++ it "parses common statement (2)" $+ sParser "common q /something/a,b,c /other/y" `shouldBe'` st++ it "parses equivalence statement" $ do+ let eqALists = fromList ()+ [ fromList ()+ [ let indicies = fromList () [ IxSingle () u Nothing (intGen 1) ]+ in ExpSubscript () u (varGen "a") indicies+ , varGen "x"+ ]+ , fromList ()+ [ varGen "y"+ , varGen "z"+ , let indicies = fromList () [ IxRange () u (Just $ intGen 1)+ (Just $ intGen 42)+ Nothing ]+ in ExpSubscript () u (varGen "d") indicies+ ]+ ]+ st = StEquivalence () u eqALists+ sParser "equivalence (a(1), x), (y, z, d(1:42))" `shouldBe'` st++ describe "Dynamic allocation" $ do+ it "parses allocate statement" $ do+ let opt = AOStat () u (varGen "a")+ allocs = fromList ()+ [ varGen "x"+ , ExpDataRef () u (varGen "st") (varGen "part")+ ]+ s = StAllocate () u Nothing allocs (Just (AList () u [opt]))+ sParser "allocate (x, st % part, STAT = a)" `shouldBe'` s++ it "parses deallocate statement" $ do+ let allocs = fromList ()+ [ let indicies = fromList () [ IxSingle () u Nothing (intGen 20) ]+ in ExpSubscript () u (varGen "smt") indicies+ ]+ s = StDeallocate () u allocs Nothing+ sParser "deallocate (smt ( 20 ))" `shouldBe'` s++ it "parses nullify statement" $ do+ let s = StNullify () u (fromList () [ varGen "x" ])+ sParser "nullify (x)" `shouldBe'` s++ it "parses pointer assignment" $ do+ let src = ExpDataRef () u (varGen "x") (varGen "y")+ st = StPointerAssign () u src (varGen "exp")+ sParser "x % y => exp" `shouldBe'` st++ describe "Where" $ do+ it "parses where statement" $ do+ let exp = ExpBinary () u Subtraction (varGen "temp") (varGen "r_temp")+ pred = ExpBinary () u GT (varGen "temp") (intGen 100)+ assignment = StExpressionAssign () u (varGen "temp") exp+ st = StWhere () u pred assignment+ sParser "where (temp > 100) temp = temp - r_temp"`shouldBe'` st++ describe "Where block" $ do+ it "parses where construct statement" $+ sParser "where (.true.)" `shouldBe'` StWhereConstruct () u Nothing valTrue++ it "parses elsewhere statement" $+ sParser "elsewhere" `shouldBe'` StElsewhere () u Nothing Nothing++ it "parses elsewhere statement" $ do+ let exp = ExpBinary () u GT (varGen "a") (varGen "b")+ sParser "elsewhere (a > b)" `shouldBe'` StElsewhere () u Nothing (Just exp)++ it "parses endwhere statement" $+ sParser "endwhere" `shouldBe'` StEndWhere () u Nothing++ describe "If" $ do+ let stPrint = StPrint () u starVal (Just $ fromList () [ ExpValue () u (ValString "foo")])+ it "parser if block" $+ let ifBlockSrc = unlines [ "if (.false.) then", "print *, 'foo'", "end if"]+ in bParser ifBlockSrc `shouldBe'` BlIf () u Nothing Nothing [Just valFalse] [[BlStatement () u Nothing stPrint]] Nothing++ it "parses named if block" $ do+ let ifBlockSrc = unlines [ "mylabel : if (.true.) then", "print *, 'foo'", "end if mylabel"]+ ifBlock = BlIf () u Nothing (Just "mylabel") [Just valTrue] [[BlStatement () u Nothing stPrint]] Nothing+ bParser ifBlockSrc `shouldBe'` ifBlock++ it "parses if-else block with inline comments (stripped)" $+ let ifBlockSrc = unlines [ "if (.false.) then ! comment if", "print *, 'foo'", "else ! comment else", "print *, 'foo'", "end if ! comment end"]+ in bParser ifBlockSrc `shouldBe'` BlIf () u Nothing Nothing [Just valFalse, Nothing] [[BlStatement () u Nothing stPrint], [BlStatement () u Nothing stPrint]] Nothing++ it "parses logical if statement" $ do+ let assignment = StExpressionAssign () u (varGen "a") (varGen "b")+ stIf = StIfLogical () u valTrue assignment+ sParser "if (.true.) a = b" `shouldBe'` stIf++ it "parses arithmetic if statement" $ do+ let stIf = StIfArithmetic () u (varGen "x") (intGen 1)+ (intGen 2)+ (intGen 3)+ sParser "if (x) 1, 2, 3" `shouldBe'` stIf++ describe "Case" $ do+ let printArgs str = Just $ AList () u [ExpValue () u $ ValString str]+ printStmt = StPrint () u (ExpValue () u ValStar) . printArgs+ printBlock = BlStatement () u Nothing . printStmt+ ind2 = AList () u . pure $ IxSingle () u Nothing $ intGen 2+ ind3Plus = AList () u . pure $ IxRange () u (Just $ intGen 3) Nothing Nothing+ conds = [Just ind2, Just ind3Plus, Nothing]+ it "unlabelled case block (with inline comments to be stripped)" $ do+ let src = unlines [ "select case (x) ! comment select"+ , "! full line before first case (unrepresentable)"+ , "case (2) ! comment case 1"+ , "print *, 'foo'"+ , "case (3:) ! comment case 2"+ , "print *, 'bar'"+ , "case default ! comment case 3"+ , "print *, 'baz'"+ , "end select ! comment end"+ ]+ blocks = (fmap . fmap) printBlock [["foo"], ["bar"], ["baz"]]+ block = BlCase () u Nothing Nothing (varGen "x") conds blocks Nothing+ bParser src `shouldBe'` block+ it "labelled case block (with inline comments to be stripped" $ do+ let src = unlines [ "10 mylabel: select case (x) ! comment select"+ , "20 case (2) ! comment case 1"+ , "30 print *, 'foo'"+ , "40 case (3:) ! comment case 2"+ , "50 print *, 'bar'"+ , "60 case default ! comment case 3"+ , "70 print *, 'baz'"+ , "80 end select mylabel ! comment end"+ ]+ blocks = (fmap . fmap)+ (\(label, arg) -> BlStatement () u (Just $ intGen label) $ printStmt arg)+ [[(30, "foo")], [(50, "bar")], [(70, "baz")]]+ block = BlCase () u+ (Just $ intGen 10) (Just "mylabel") (varGen "x")+ conds blocks+ (Just $ intGen 80)+ bParser src `shouldBe'` block++ describe "Do" $ do+ it "parses do statement with label" $ do+ let assign = StExpressionAssign () u (varGen "i") (intGen 0)+ doSpec = DoSpecification () u assign (intGen 42) Nothing+ st = StDo () u Nothing (Just $ intGen 24) (Just doSpec)+ sParser "do 24, i = 0, 42" `shouldBe'` st++ it "parses do statement without label" $ do+ let assign = StExpressionAssign () u (varGen "i") (intGen 0)+ doSpec = DoSpecification () u assign (intGen 42) Nothing+ st = StDo () u Nothing Nothing (Just doSpec)+ sParser "do i = 0, 42" `shouldBe'` st++ it "parses infinite do" $ do+ let st = StDo () u Nothing Nothing Nothing+ sParser "do" `shouldBe'` st++ it "parses end do statement" $ do+ let st = StEnddo () u (Just "constructor")+ sParser "end do constructor" `shouldBe'` st++ describe "DO WHILE" $ do+ it "parses unnamed do while statement" $ do+ let st = StDoWhile () u Nothing Nothing valTrue+ sParser "do while (.true.)" `shouldBe'` st++ it "parses named do while statement" $ do+ let st = StDoWhile () u (Just "name") Nothing valTrue+ sParser "name: do while (.true.)" `shouldBe'` st++ it "parses unnamed labelled do while statement" $ do+ let st = StDoWhile () u Nothing (Just (intGen 999)) valTrue+ sParser "do 999 while (.true.)" `shouldBe'` st++ describe "Goto" $ do+ it "parses vanilla goto" $ do+ let st = StGotoUnconditional () u (intGen 999)+ sParser "goto 999" `shouldBe'` st++ it "parses computed goto" $ do+ let list = fromList () [ intGen 10, intGen 20, intGen 30 ]+ st = StGotoComputed () u list (intGen 20)+ sParser "goto (10, 20, 30) 20" `shouldBe'` st++ it "doesn't parse assigned goto" $+ evaluate (sParser "goto i, (10, 20, 30)") `shouldThrow` anyIOException++ it "doesn't parse label assignment" $+ evaluate (sParser "assign 20 to l") `shouldThrow` anyIOException++ describe "IO" $ do+ it "parses vanilla print" $ do+ let st = StPrint () u starVal (Just $ fromList () [ varGen "hex" ])+ sParser "print *, hex" `shouldBe'` st++ it "parses write with implied do" $ do+ let cp1 = ControlPair () u Nothing (intGen 10)+ cp2 = ControlPair () u (Just "format") (varGen "x")+ ciList = fromList () [ cp1, cp2 ]+ assign = StExpressionAssign () u (varGen "i") (intGen 1)+ doSpec = DoSpecification () u assign (intGen 42) (Just $ intGen 2)+ alist = fromList () [ varGen "i", varGen "j" ]+ outList = fromList () [ ExpImpliedDo () u alist doSpec ]+ st = StWrite () u ciList (Just outList)+ sParser "write (10, FORMAT = x) (i, j, i = 1, 42, 2)" `shouldBe'` st++ it "parses use statement" $ do+ let renames = fromList ()+ [ UseRename () u (varGen "sprod") (varGen "prod")+ , UseRename () u (varGen "a") (varGen "b") ]+ st = StUse () u (varGen "stats_lib") Nothing Permissive (Just renames)+ sParser "use stats_lib, sprod => prod, a => b" `shouldBe'` st++ it "parses value decl" $ do+ let decls = [declVarGen "a", declVarGen "b"]+ st = StValue () u (AList () u decls)+ sParser "value a, b" `shouldBe'` st+ sParser "value :: a, b" `shouldBe'` st++ it "parses value attribute" $ do+ let decls = [declVarGen "a", declVarGen "b"]+ ty = TypeSpec () u TypeInteger Nothing+ attrs = [AttrValue () u]+ st = StDeclaration () u ty (Just (AList () u attrs)) (AList () u decls)+ sParser "integer, value :: a, b" `shouldBe'` st++ it "parses volatile decl" $ do+ let decls = [declVarGen "a", declVarGen "b"]+ st = StVolatile () u (AList () u decls)+ sParser "volatile a, b" `shouldBe'` st+ sParser "volatile :: a, b" `shouldBe'` st++ it "parses volatile attribute" $ do+ let decls = [declVarGen "a", declVarGen "b"]+ ty = TypeSpec () u TypeInteger Nothing+ attrs = [AttrVolatile () u]+ st = StDeclaration () u ty (Just (AList () u attrs)) (AList () u decls)+ sParser "integer, volatile :: a, b" `shouldBe'` st++ specFreeCommon sParser eParser
+ test/Language/Fortran/Parser/Free/LexerSpec.hs view
@@ -0,0 +1,383 @@+module Language.Fortran.Parser.Free.LexerSpec ( spec ) where++import Test.Hspec+import TestUtil++import Language.Fortran.Parser.Free.Lexer ( Token(..), lexer' )+import Language.Fortran.Parser ( collectTokens )+import Language.Fortran.Parser ( initParseStateFree )+import Language.Fortran.AST.RealLit+import Language.Fortran.Version+import Language.Fortran.Util.Position (SrcSpan)++import qualified Data.ByteString.Char8 as B++collectFreeTokens :: FortranVersion -> B.ByteString -> [Token]+collectFreeTokens fv bs =+ collectTokens lexer' $ initParseStateFree "<unknown>" fv bs++collectF90 :: String -> [Token]+collectF90 = collectFreeTokens Fortran90 . B.pack++collectF03 :: String -> [Token]+collectF03 = collectFreeTokens Fortran2003 . B.pack++pseudoAssign :: (SrcSpan -> Token) -> [Token]+pseudoAssign token = fmap ($u) [ flip TId "i", TOpAssign, token, TEOF ]++spec :: Spec+spec =+ describe "Fortran Free Form Lexer" $+ describe "Fortran 90" $ do+ describe "Character sensitivity" $ do+ it "lexes lower case tokens" $+ shouldBe' (collectF90 "integer id") $+ fmap ($u) [ TInteger, flip TId "id", TEOF ]++ it "lexes mixed case tokens" $+ shouldBe' (collectF90 "InTEgeR ID") $+ fmap ($u) [ TInteger, flip TId "id", TEOF ]++ describe "Identifier" $ do+ it "lexes long ID names" $+ shouldBe' (collectF90 "program long_id_name") $+ fmap ($u) [ TProgram, flip TId "long_id_name", TEOF ]++ it "treats 'if' as ID if used in assignment" $+ shouldBe' (collectF90 "if = 20") $+ fmap ($u) [ flip TId "if", TOpAssign+ , flip TIntegerLiteral "20", TEOF ]++ it "'result' is an identifier in spec. context" $+ shouldBe' (collectF90 "integer :: result") $+ fmap ($u) [ TInteger, TDoubleColon , flip TId "result"+ , TEOF ]++ describe "Types" $ do+ it "lexes length and kind selectors" $+ shouldBe' (collectF90 "integer (KIND=1, LEN=1) :: kind, len") $+ fmap ($u) [ TInteger, TLeftPar, TKind, TOpAssign+ , flip TIntegerLiteral "1", TComma, TLen+ , TOpAssign, flip TIntegerLiteral "1", TRightPar+ , TDoubleColon , flip TId "kind", TComma+ , flip TId "len", TEOF ]+++ it "lexes simple type tokens" $+ shouldBe' (collectF90 "character x") $+ fmap ($u) [ TCharacter, flip TId "x", TEOF ]++ it "lexes simple type tokens in function" $+ shouldBe' (collectF90 "character function x") $+ fmap ($u) [ TCharacter, TFunction, flip TId "x", TEOF ]++ it "lexes character type with F77 length syntax (1)" $+ shouldBe' (collectF90 "character * (*) function x") $+ fmap ($u) [ TCharacter, TStar, TLeftPar, TStar, TRightPar, TFunction, flip TId "x", TEOF ]++ it "lexes character type with F77 length syntax (2)" $+ shouldBe' (collectF90 "character * 20 function x") $+ fmap ($u) [ TCharacter, TStar, flip TIntegerLiteral "20", TFunction, flip TId "x", TEOF ]++ it "lexes derived type tokens in function" $+ shouldBe' (collectF90 "type (x) function x") $+ fmap ($u) [ TType, TLeftPar, flip TId "x", TRightPar+ , TFunction, flip TId "x", TEOF ]++ it "lexes interleaved type recursive tokens" $+ shouldBe' (collectF90 "integer (KIND=10*2) recursive function x") $+ fmap ($u) [ TInteger, TLeftPar, TKind, TOpAssign+ , flip TIntegerLiteral "10" , TStar+ , flip TIntegerLiteral "2", TRightPar, TRecursive+ , TFunction, flip TId "x", TEOF ]++ it "lexes interleaved type recursive tokens (reversed)" $+ shouldBe' (collectF90 "recursive integer (KIND=10*2) function x") $+ fmap ($u) [ TRecursive, TInteger, TLeftPar, TKind, TOpAssign+ , flip TIntegerLiteral "10" , TStar+ , flip TIntegerLiteral "2", TRightPar, TFunction+ , flip TId "x", TEOF ]++ describe "Function" $ do+ it "lexes 'function fx ( a, b, c )'" $+ shouldBe' (collectF90 "function fx ( a, b )") $+ fmap ($u) [ TFunction, flip TId "fx", TLeftPar, flip TId "a"+ , TComma, flip TId "b", TRightPar, TEOF ]++ it "lexes functions with specific result" $+ shouldBe' (collectF90 "function fx (array) result (c_sum)") $+ fmap ($u) [ TFunction, flip TId "fx", TLeftPar+ , flip TId "array", TRightPar, TResult, TLeftPar+ , flip TId "c_sum", TRightPar, TEOF ]++ it "lexes recursive functions" $+ shouldBe' (collectF90 "recursive function fx (array)") $+ fmap ($u) [ TRecursive, TFunction, flip TId "fx", TLeftPar+ , flip TId "array", TRightPar, TEOF ]++ it "lexes recursive functions with result specified" $+ shouldBe' (collectF90 "RECURSIVE FUNCTION FX (ARRAY) RESULT (C_SUM)") $+ fmap ($u) [ TRecursive, TFunction, flip TId "fx", TLeftPar+ , flip TId "array", TRightPar, TResult, TLeftPar+ , flip TId "c_sum", TRightPar, TEOF ]++ describe "Attribute" $ do+ it "lexes PARAMETER attribute" $+ shouldBe' (collectF90 "integer, parameter :: x") $+ fmap ($u) [ TInteger, TComma, TParameter, TDoubleColon+ , flip TId "x", TEOF ]++ it "lexes INTENT attribute" $+ shouldBe' (collectF90 "integer, intent (inout) :: x") $+ fmap ($u) [ TInteger, TComma, TIntent, TLeftPar, TInOut+ , TRightPar, TDoubleColon , flip TId "x", TEOF ]++ it "lexes DIMENSION attribute" $+ shouldBe' (collectF90 "double precision, dimension (3:10) :: x") $+ fmap ($u) [ TDoublePrecision, TComma, TDimension, TLeftPar+ , flip TIntegerLiteral "3", TColon+ , flip TIntegerLiteral "10" , TRightPar+ , TDoubleColon , flip TId "x", TEOF ]++ it "lexes variable declaration with multiple attributes" $+ shouldBe' (collectF90 "double precision, save, dimension(2), allocatable :: y") $+ fmap ($u) [ TDoublePrecision, TComma, TSave, TComma+ , TDimension, TLeftPar, flip TIntegerLiteral "2"+ , TRightPar, TComma, TAllocatable, TDoubleColon+ , flip TId "y", TEOF ]++ it "try to trick lexer into parsing variables as attributes (1)" $+ shouldBe' (collectF90 "integer save, dimension(10), target") $+ fmap ($u) [ TInteger, flip TId "save", TComma+ , flip TId "dimension", TLeftPar, flip TIntegerLiteral "10", TRightPar, TComma+ , flip TId "target", TEOF ]++ it "try to trick lexer into parsing variables as attributes (2)" $+ shouldBe' (collectF90 "type(foo) save, dimension(10), target") $+ fmap ($u) [ TType, TLeftPar, flip TId "foo", TRightPar, flip TId "save", TComma+ , flip TId "dimension", TLeftPar, flip TIntegerLiteral "10", TRightPar, TComma+ , flip TId "target", TEOF ]++ it "try to trick lexer into parsing variables as attributes (3)" $+ shouldBe' (collectF90 "allocate(type(foo) :: errmsg(stat, source), source=x)") $+ fmap ($u) [ TAllocate, TLeftPar, TType, TLeftPar, flip TId "foo", TRightPar, TDoubleColon+ , flip TId "errmsg", TLeftPar, flip TId "stat", TComma, flip TId "source", TRightPar+ , TComma, TSource, TOpAssign, flip TId "x", TRightPar, TEOF ]++ describe "Character" $ do+ it "lexes single quote literal" $+ shouldBe' (collectF90 "character c = 'heL\"Lo ''daRLing'") $+ fmap ($u) [ TCharacter, flip TId "c", TOpAssign+ , flip TString "heL\"Lo 'daRLing", TEOF ]++ it "lexes double quote literal" $+ shouldBe' (collectF90 "character c = \"heL'Lo \"\"daRLing\"") $+ fmap ($u) [ TCharacter, flip TId "c", TOpAssign+ , flip TString "heL'Lo \"daRLing", TEOF ]++ describe "Module" $ do+ it "lexes module statement" $+ shouldBe' (collectF90 "module Hello_mod") $+ fmap ($u) [ TModule, flip TId "hello_mod", TEOF ]++ it "lexes use statement" $+ shouldBe' (collectF90 "use Hello_mod, hello => hi") $+ fmap ($u) [ TUse, flip TId "hello_mod", TComma+ , flip TId "hello", TArrow, flip TId "hi", TEOF ]++ it "lexes use statement with only" $+ shouldBe' (collectF90 "use Hello_mod, only: a, b => c") $+ fmap ($u) [ TUse, flip TId "hello_mod", TComma, TOnly+ , TColon, flip TId "a", TComma, flip TId "b"+ , TArrow, flip TId "c", TEOF ]++ describe "Label" $+ it "lexes simple label" $+ shouldBe' (collectF90 "010 print *, 'hello'") $+ fmap ($u) [ flip TIntegerLiteral "010", TPrint, TStar, TComma+ , flip TString "hello", TEOF ]++ describe "Conditional" $ do+ it "lexes logical if with array assignment" $+ shouldBe' (collectF90 "if (.true.) a(1) = 42") $+ fmap ($u) [ TIf, TLeftPar, flip TLogicalLiteral True+ , TRightPar, flip TId "a", TLeftPar+ , flip TIntegerLiteral "1", TRightPar, TOpAssign+ , flip TIntegerLiteral "42", TEOF ]++ it "lexes block if statement" $+ shouldBe' (collectF90 "if (a > b) then") $+ fmap ($u) [ TIf, TLeftPar, flip TId "a", TOpGT, flip TId "b"+ , TRightPar, TThen, TEOF ]++ it "lexes arithmetic if statement" $+ shouldBe' (collectF90 "if (a) 10, 11, 12") $+ fmap ($u) [ TIf, TLeftPar, flip TId "a", TRightPar+ , flip TIntegerLiteral "10", TComma+ , flip TIntegerLiteral "11", TComma+ , flip TIntegerLiteral "12" , TEOF ]++ it "lexes logical if statement" $+ shouldBe' (collectF90 "if (a > b) print *, 'hello'") $+ fmap ($u) [ TIf, TLeftPar, flip TId "a", TOpGT, flip TId "b"+ , TRightPar, TPrint, TStar, TComma+ , flip TString "hello", TEOF ]++ describe "Lexes numeric values" $ do+ it "lexes integer" $+ shouldBe' (collectF90 "i = 42") $+ pseudoAssign $ flip TIntegerLiteral "42"++ describe "Real" $ do+ it "lexes real (1)" $ do+ let litStr = "10.5e2"+ expectedLit = RealLit "10.5" (Exponent ExpLetterE "2")+ expected = pseudoAssign $ flip TRealLiteral expectedLit+ collectF90 ("i = "<>litStr) `shouldBe'` expected++ it "lexes real (2)" $ do+ let litStr = "10."+ expectedLit = RealLit "10.0" (Exponent ExpLetterE "0")+ expected = pseudoAssign $ flip TRealLiteral expectedLit+ collectF90 ("i = "<>litStr) `shouldBe'` expected++ it "lexes real (3)" $ do+ let litStr = ".42"+ expectedLit = RealLit "0.42" (Exponent ExpLetterE "0")+ expected = pseudoAssign $ flip TRealLiteral expectedLit+ collectF90 ("i = "<>litStr) `shouldBe'` expected++ it "lexes real (4)" $ do+ let litStr = "42d-3"+ expectedLit = RealLit "42.0" (Exponent ExpLetterD "-3")+ expected = pseudoAssign $ flip TRealLiteral expectedLit+ collectF90 ("i = "<>litStr) `shouldBe'` expected++ it "resolves disambiguity when xxx. follows relational operator" $+ shouldBe' (collectF90 "if (10.EQ. 20)") $+ fmap ($u) [ TIf, TLeftPar, flip TIntegerLiteral "10"+ , TOpEQ, flip TIntegerLiteral "20"+ , TRightPar, TEOF ]++ describe "Continuation" $ do+ it "Single continuation char without space" $+ shouldBe' (collectF90 "i = &\n42") $+ pseudoAssign $ flip TIntegerLiteral "42"++ it "Single continuation char with space" $+ shouldBe' (collectF90 "i = & \n \t 42") $+ pseudoAssign $ flip TIntegerLiteral "42"++ it "Double continuation (1)" $+ shouldBe' (collectF90 "i = &\n & 42") $+ pseudoAssign $ flip TIntegerLiteral "42"++ it "Double continuation (2)" $+ shouldBe' (collectF90 "i = 4&\n &2") $+ pseudoAssign $ flip TIntegerLiteral "42"++ it "Continuation with comment" $+ shouldBe' (collectF90 "i = 4&\n ! hello\n &2") $+ pseudoAssign $ flip TIntegerLiteral "42"++ it "Continuation with inline comment" $+ shouldBe' (collectF90 "i = & ! hi \n 42") $+ pseudoAssign $ flip TIntegerLiteral "42"++ describe "Comment" $ do+ it "Full line comment" $+ shouldBe' (collectF90 "! = & ! hi \n") $+ ($u) <$> [ flip TComment " = & ! hi ", TNewline , TEOF ]++ it "Inline comment" $+ shouldBe' (collectF90 "i = 10 ! = & ! hi \n") $+ ($u) <$> [ flip TId "i", TOpAssign+ , flip TIntegerLiteral "10"+ , flip TComment " = & ! hi ", TNewline , TEOF ]+ it "Empty comment" $+ shouldBe' (collectF90 "!\n") $+ ($u) <$> [ flip TComment "", TNewline , TEOF ]++ describe "Subscripting" $ do+ it "Strings nested in arrays" $+ shouldBe' (collectF90 "a(1)(2:3) = 'we'") $+ ($u) <$> [ flip TId "a", TLeftPar, flip TIntegerLiteral "1", TRightPar+ , TLeftPar, flip TIntegerLiteral "2", TColon, flip TIntegerLiteral "3", TRightPar+ , TOpAssign, flip TString "we", TEOF ]++ describe "Fortran95" $ do+ it "lexes value attribute" $ do+ shouldBe' (collectF03 "value :: a, b") $+ fmap ($u) [ TValue, TDoubleColon, flip TId "a", TComma, flip TId "b", TEOF ]+ shouldBe' (collectF03 "integer, value :: a, b") $+ fmap ($u) [ TInteger, TComma, TValue, TDoubleColon, flip TId "a", TComma, flip TId "b", TEOF ]++ it "lexes volatile attribute" $ do+ shouldBe' (collectF03 "volatile :: a, b") $+ fmap ($u) [ TVolatile, TDoubleColon, flip TId "a", TComma, flip TId "b", TEOF ]+ shouldBe' (collectF03 "integer, volatile :: a, b") $+ fmap ($u) [ TInteger, TComma, TVolatile, TDoubleColon, flip TId "a", TComma, flip TId "b", TEOF ]++ describe "Fortran2003" $ do+ it "lexes procedures" $+ shouldBe' (collectF03 "PROCEDURE(a), SAVE :: b => c()") $+ ($u) <$> [ TProcedure, TLeftPar, flip TId "a", TRightPar+ , TComma, TSave, TDoubleColon+ , flip TId "b", TArrow, flip TId "c", TLeftPar, TRightPar, TEOF ]++ it "lexes procedures with bind" $+ shouldBe' (collectF03 "PROCEDURE(a), BIND(C, NAME=\"d\") :: b => c()") $+ ($u) <$> [ TProcedure, TLeftPar, flip TId "a", TRightPar+ , TComma, TBind, TLeftPar, TC, TComma, TName, TOpAssign, flip TString "d", TRightPar, TDoubleColon+ , flip TId "b", TArrow, flip TId "c", TLeftPar, TRightPar, TEOF ]++ it "lexes functions with bind" $+ shouldBe' (collectF03 "FUNCTION f(a) RESULT(x) BIND(C, NAME=\"d\")") $+ ($u) <$> [ TFunction, flip TId "f", TLeftPar, flip TId "a", TRightPar+ , TResult, TLeftPar, flip TId "x", TRightPar+ , TBind, TLeftPar, TC, TComma, TName, TOpAssign, flip TString "d", TRightPar, TEOF ]++ it "lexes subroutines with bind" $+ shouldBe' (collectF03 "SUBROUTINE s(a) BIND(C, NAME=\"d\")") $+ ($u) <$> [ TSubroutine, flip TId "s", TLeftPar, flip TId "a", TRightPar+ , TBind, TLeftPar, TC, TComma, TName, TOpAssign, flip TString "d", TRightPar, TEOF ]++ it "lexes class decl (name)" $+ shouldBe' (collectF03 "procedure (class(c))") $+ fmap ($u) [ TProcedure, TLeftPar+ , TClass, TLeftPar, flip TId "c", TRightPar, TRightPar, TEOF ]++ it "lexes class decl (*)" $+ shouldBe' (collectF03 "procedure (class(*))") $+ fmap ($u) [ TProcedure, TLeftPar+ , TClass, TLeftPar, TStar, TRightPar, TRightPar, TEOF ]++ it "lexes import statements" $+ shouldBe' (collectF03 "import :: a, b") $+ fmap ($u) [ TImport, TDoubleColon, flip TId "a", TComma, flip TId "b", TEOF ]++ it "lexes asynchronous attribute" $ do+ shouldBe' (collectF03 "asynchronous :: a, b") $+ fmap ($u) [ TAsynchronous, TDoubleColon, flip TId "a", TComma, flip TId "b", TEOF ]+ shouldBe' (collectF03 "integer, asynchronous :: a, b") $+ fmap ($u) [ TInteger, TComma, TAsynchronous, TDoubleColon, flip TId "a", TComma, flip TId "b", TEOF ]++ it "lexes enums" $ do+ shouldBe' (collectF03 "enum, bind(c)") $ fmap ($u) [ TEnum, TComma, TBind, TLeftPar, TC, TRightPar, TEOF ]+ shouldBe' (collectF03 "enumerator :: a = 1, b") $+ fmap ($u) [ TEnumerator, TDoubleColon, flip TId "a", TOpAssign, flip TIntegerLiteral "1"+ , TComma, flip TId "b", TEOF ]+ shouldBe' (collectF03 "end enum") $ fmap ($u) [ TEndEnum, TEOF ]++ it "lexes flush" $ do+ shouldBe' (collectF03 "flush(unit=1)") $+ fmap ($u) [ TFlush, TLeftPar, TUnit, TOpAssign, flip TIntegerLiteral "1", TRightPar, TEOF ]+ shouldBe' (collectF03 "flush(unit=1,iomsg=x,iostat=y,err=z)") $+ fmap ($u) [ TFlush, TLeftPar, TUnit, TOpAssign, flip TIntegerLiteral "1", TComma+ , TIOMsg, TOpAssign, flip TId "x", TComma+ , TIOStat, TOpAssign, flip TId "y", TComma+ , TErr, TOpAssign, flip TId "z", TRightPar, TEOF ]++ it "lexes protected" $ do+ shouldBe' (collectF03 "real, protected, public :: x") $+ fmap ($u) [ TReal, TComma, TProtected, TComma, TPublic, TDoubleColon, flip TId "x", TEOF ]
− test/Language/Fortran/Parser/FreeFormCommon.hs
@@ -1,68 +0,0 @@--- | Fortran standards F90 and beyond are a lot more consistent than the--- previous 2. As such, there is lots of shared parsing, and lots of shared--- tests. This module encodes such shared/common tests, where no difference--- in behaviour between parsers is be expected.--module Language.Fortran.Parser.FreeFormCommon ( specFreeFormCommon ) where--import TestUtil-import Test.Hspec--import Language.Fortran.AST-import Language.Fortran.AST.RealLit--specFreeFormCommon :: (String -> Statement A0) -> (String -> Expression A0) -> Spec-specFreeFormCommon sParser eParser =- describe "Common Fortran 90+ tests" $ do- describe "Literals" $ do- describe "Logical" $ do- it "parses logical literal without kind parameter" $ do- eParser ".true." `shouldBe'` valTrue-- it "parses logical literal with kind parameter" $ do- let kp = ExpValue () u (ValVariable "kind")- eParser ".false._kind" `shouldBe'` valFalse' kp-- it "parses mixed-case logical literal" $ do- eParser ".tRUe." `shouldBe'` valTrue-- -- Main parse testing is performed in @Language.Fortran.AST.RealLitSpec@.- -- Here we mainly want to test kind parameter and sign behaviour.- describe "Real" $ do- let realLitExp r mkp = ExpValue () u (ValReal (parseRealLit r) mkp)- it "parses various REAL literals" $ do- eParser "1." `shouldBe'` realLitExp "1." Nothing- eParser ".1e20_8" `shouldBe'` realLitExp ".1e20" (Just (intGen 8))-- it "parses \"negative\" real literal (unary op)" $ do- eParser "-1.0d-1_k8" `shouldBe'` ExpUnary () u Minus (realLitExp "1.0d-1" (Just (varGen "k8")))-- describe "Statement" $ do- describe "Declaration" $ do- it "parses scalar declaration with nonstandard kind param (non-CHAR)" $ do- let stStr = "integer x*8"- expected = StDeclaration () u typeSpec Nothing decls- typeSpec = TypeSpec () u TypeInteger Nothing- decls = AList () u- [ declVariable () u (varGen "x") (Just (intGen 8)) Nothing ]- sParser stStr `shouldBe'` expected-- it "parses array declaration with nonstandard kind param (non-CHAR)" $ do- let stStr = "integer x(2)*8"- expected = StDeclaration () u typeSpec Nothing decls- typeSpec = TypeSpec () u TypeInteger Nothing- decls = AList () u- [ declArray () u (varGen "x") dims (Just (intGen 8)) Nothing ]- dims = AList () u- [ DimensionDeclarator () u Nothing (Just (intGen 2)) ]- sParser stStr `shouldBe'` expected-- it "parses array declaration with nonstandard kind param (non-CHAR) and nonstandard dimension/charlen order" $ do- let stStr = "integer x*8(2)"- expected = StDeclaration () u typeSpec Nothing decls- typeSpec = TypeSpec () u TypeInteger Nothing- decls = AList () u- [ declArray () u (varGen "x") dims (Just (intGen 8)) Nothing ]- dims = AList () u- [ DimensionDeclarator () u Nothing (Just (intGen 2)) ]- sParser stStr `shouldBe'` expected
+ test/Language/Fortran/Parser/MonadSpec.hs view
@@ -0,0 +1,91 @@+{-# OPTIONS_GHC -Wno-orphans #-}++module Language.Fortran.Parser.MonadSpec where++import Test.Hspec++import Language.Fortran.Parser.Monad+import Language.Fortran.Version+import Language.Fortran.Util.Position++vanillaParseState :: ParseState String+vanillaParseState = ParseState+ { psAlexInput = ""+ , psVersion = Fortran66+ , psFilename = "<unknown>"+ , psParanthesesCount = ParanthesesCount 0 False+ , psContext = [ ConStart ]+ }++instance Loc String where+ getPos = error "Never needed"++instance LastToken String String where+ getLastToken = error "Never needed"++data SomeInput = SomeInput { p :: Position }++initPos :: Position+initPos = Position 5 1 2 "" Nothing++initSomeInput :: SomeInput+initSomeInput = SomeInput { p = initPos }++instance Loc SomeInput where+ getPos = p++instance LastToken SomeInput String where+ getLastToken = error "Never needed"++vanillaSomeInput :: ParseState SomeInput+vanillaSomeInput = ParseState+ { psAlexInput = initSomeInput+ , psVersion = Fortran66+ , psFilename = "some.f"+ , psParanthesesCount = ParanthesesCount 0 False+ , psContext = [ ConStart ]+ }++spec :: Spec+spec =+ describe "ParserMonad" $ do+ describe "Parse" $ do+ it "should give out correct version" $+ evalParse getVersion vanillaParseState `shouldBe` Fortran66++ it "satisfies read after write equals to what is written" $+ let ai = evalParse (putAlex "l'enfer" >> getAlex) vanillaParseState in+ ai `shouldBe` "l'enfer"++ describe "Obtaining locations" $ do+ it "getPosition returns correct location" $+ let _expPosition = Position 6 2 3 "some.f" Nothing+ _exampleM = do+ _ai <- getAlex+ putAlex $ _ai { p = _expPosition }+ getPosition+ _loc = evalParse _exampleM vanillaSomeInput in+ _loc `shouldBe` _expPosition++ it "getSrcSpan return correct location span" $+ let _loc2 = Position 6 2 3 "some.f" Nothing+ _exampleM = do+ _ai <- getAlex+ _loc1 <- getPosition+ putAlex $ _ai { p = _loc2 }+ getSrcSpan _loc1+ _span = evalParse _exampleM vanillaSomeInput+ _expectation = SrcSpan initPos _loc2 in+ _span `shouldBe` _expectation++ describe "Lex" $ do+ it "reads the state correctly" $+ evalParse getAlex vanillaParseState `shouldBe` ""++ it "overrides the state correctly" $+ let ai = evalParse (putAlex "c'est" >> getAlex) vanillaParseState in+ ai `shouldBe` "c'est"++ it "mixes operations correctly" $+ let ai = evalParse (putAlex "hello" >> getAlex >>= \s -> putAlex (take 4 s) >> getAlex) vanillaParseState in+ ai `shouldBe` "hell"
− test/Language/Fortran/Parser/UtilsSpec.hs
@@ -1,29 +0,0 @@-module Language.Fortran.Parser.UtilsSpec where--import Test.Hspec--import Language.Fortran.Parser.Utils--spec :: Spec-spec =- describe "Fortran Parser Utils" $ do-- describe "readReal" $ do- it "tests" $ do- readReal "+12" `shouldBe` Just 12- readReal "-1.2" `shouldBe` Just (-1.2)- readReal "1.2d3" `shouldBe` Just 1200- readReal "1.e2" `shouldBe` Just 100- readReal "1.e-2" `shouldBe` Just 0.01- readReal ".12" `shouldBe` Just 0.12- readReal "-.12" `shouldBe` Just (-0.12)- readReal "1_f" `shouldBe` Just 1-- describe "readInteger" $ do- it "tests" $ do- readInteger "b'101'" `shouldBe` Just 5- readInteger "o'22'" `shouldBe` Just 18- readInteger "z'AF'" `shouldBe` Just 175- readInteger "1_f" `shouldBe` Just 1- readInteger "+123" `shouldBe` Just 123- readInteger "-123" `shouldBe` Just (-123)
− test/Language/Fortran/ParserMonadSpec.hs
@@ -1,92 +0,0 @@-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE MultiParamTypeClasses #-}-{-# OPTIONS_GHC -Wno-orphans #-}--module Language.Fortran.ParserMonadSpec where--import Test.Hspec--import Language.Fortran.ParserMonad-import Language.Fortran.Util.Position--vanillaParseState :: ParseState String-vanillaParseState = ParseState- { psAlexInput = ""- , psVersion = Fortran66- , psFilename = "<unknown>"- , psParanthesesCount = ParanthesesCount 0 False- , psContext = [ ConStart ]- }--instance Loc String where- getPos = error "Never needed"--instance LastToken String String where- getLastToken = error "Never needed"--data SomeInput = SomeInput { p :: Position }--initPos :: Position-initPos = Position 5 1 2 "" Nothing--initSomeInput :: SomeInput-initSomeInput = SomeInput { p = initPos }--instance Loc SomeInput where- getPos = p--instance LastToken SomeInput String where- getLastToken = error "Never needed"--vanillaSomeInput :: ParseState SomeInput-vanillaSomeInput = ParseState- { psAlexInput = initSomeInput- , psVersion = Fortran66- , psFilename = "some.f"- , psParanthesesCount = ParanthesesCount 0 False- , psContext = [ ConStart ]- }--spec :: Spec-spec =- describe "ParserMonad" $ do- describe "Parse" $ do- it "should give out correct version" $- evalParse getVersion vanillaParseState `shouldBe` Fortran66-- it "satisfies read after write equals to what is written" $- let ai = evalParse (putAlex "l'enfer" >> getAlex) vanillaParseState in- ai `shouldBe` "l'enfer"-- describe "Obtaining locations" $ do- it "getPosition returns correct location" $- let _expPosition = Position 6 2 3 "some.f" Nothing- _exampleM = do- _ai <- getAlex- putAlex $ _ai { p = _expPosition }- getPosition- _loc = evalParse _exampleM vanillaSomeInput in- _loc `shouldBe` _expPosition-- it "getSrcSpan return correct location span" $- let _loc2 = Position 6 2 3 "some.f" Nothing- _exampleM = do- _ai <- getAlex- _loc1 <- getPosition- putAlex $ _ai { p = _loc2 }- getSrcSpan _loc1- _span = evalParse _exampleM vanillaSomeInput- _expectation = SrcSpan initPos _loc2 in- _span `shouldBe` _expectation-- describe "Lex" $ do- it "reads the state correctly" $- evalParse getAlex vanillaParseState `shouldBe` ""-- it "overrides the state correctly" $- let ai = evalParse (putAlex "c'est" >> getAlex) vanillaParseState in- ai `shouldBe` "c'est"-- it "mixes operations correctly" $- let ai = evalParse (putAlex "hello" >> getAlex >>= \s -> putAlex (take 4 s) >> getAlex) vanillaParseState in- ai `shouldBe` "hell"
test/Language/Fortran/PrettyPrintSpec.hs view
@@ -1,5 +1,4 @@ {-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE OverloadedStrings #-} module Language.Fortran.PrettyPrintSpec where@@ -12,7 +11,7 @@ import Language.Fortran.AST as LFA import Language.Fortran.AST.Boz-import Language.Fortran.ParserMonad+import Language.Fortran.Version import Language.Fortran.PrettyPrint import Text.PrettyPrint hiding ((<>))
test/Language/Fortran/Transformation/Disambiguation/FunctionSpec.hs view
@@ -4,41 +4,48 @@ import TestUtil import Language.Fortran.AST-import Language.Fortran.Transformer+import Language.Fortran.Transformation.Monad+import Language.Fortran.Transformation.Disambiguation.Function+import Language.Fortran.Transformation.Disambiguation.Intrinsic+import Data.Data -disambiguateFunction :: ProgramFile () -> ProgramFile ()-disambiguateFunction = transform [ DisambiguateIntrinsic, DisambiguateFunction ]+disambiguateFunction' :: Data a => ProgramFile a -> ProgramFile a+disambiguateFunction' = transformWith $ sequence_ [ disambiguateIntrinsic+ , disambiguateFunction ] +transformWith :: Data a => Transform a () -> ProgramFile a -> ProgramFile a+transformWith = runTransform mempty mempty+ spec :: Spec spec = do describe "Function statement disambiguation" $ it "disambiguates function statements in example 1" $ do- let pf = disambiguateFunction $ resetSrcSpan ex1+ let pf = disambiguateFunction' $ resetSrcSpan ex1 pf `shouldBe'` expectedEx1 describe "Function call disambiguation" $ it "disambiguates function calls in example 2" $ do- let pf = disambiguateFunction $ resetSrcSpan ex2+ let pf = disambiguateFunction' $ resetSrcSpan ex2 pf `shouldBe'` expectedEx2 describe "Function call / Intrinsic disambiguation" $ it "disambiguates function calls / intrinsics in example 3" $ do- let pf = disambiguateFunction $ resetSrcSpan ex3+ let pf = disambiguateFunction' $ resetSrcSpan ex3 pf `shouldBe'` expectedEx3 describe "Function call / Variable disambiguation" $ it "disambiguates function calls in example 4" $ do- let pf = disambiguateFunction $ resetSrcSpan ex4+ let pf = disambiguateFunction' $ resetSrcSpan ex4 pf `shouldBe'` expectedEx4 describe "Implicit Function call / Variable disambiguation" $ it "disambiguates function calls in example 5" $ do- let pf = disambiguateFunction $ resetSrcSpan ex5+ let pf = disambiguateFunction' $ resetSrcSpan ex5 pf `shouldBe'` expectedEx5 describe "Implicit array declaration with dimension disambiguation" $ it "Should not disambiguation to a function call in example 6" $ do- let pf = disambiguateFunction $ resetSrcSpan ex6+ let pf = disambiguateFunction' $ resetSrcSpan ex6 pf `shouldBe'` expectedEx6 {-@@ -148,7 +155,7 @@ (intGen 1) (ExpFunctionCall () u (ExpValue () u $ ValVariable "f")- (Just $ AList () u [ Argument () u Nothing (intGen 1) ])))) ]+ (Just $ AList () u [ Argument () u Nothing (aintGen 1) ])))) ] ex3 :: ProgramFile ()@@ -185,8 +192,8 @@ (StExpressionAssign () u (varGen "i") (ExpFunctionCall () u (ExpValue () u $ ValIntrinsic "abs") (Just $ AList () u [ Argument () u Nothing- (ExpFunctionCall () u (ExpValue () u $ ValVariable "f")- (Just $ AList () u [ Argument () u Nothing (intGen 1) ])) ]))) ]+ (ArgExpr $ ExpFunctionCall () u (ExpValue () u $ ValVariable "f")+ (Just $ AList () u [ Argument () u Nothing (aintGen 1) ])) ]))) ] {-@@ -221,7 +228,7 @@ , BlStatement () u Nothing (StExpressionAssign () u (varGen "a") (ExpFunctionCall () u (ExpValue () u $ ValVariable "f")- (Just $ AList () u [ Argument () u Nothing (intGen 1) ] ))) ]+ (Just $ AList () u [ Argument () u Nothing (aintGen 1) ] ))) ] {- - program Main@@ -253,7 +260,7 @@ , BlStatement () u Nothing (StExpressionAssign () u (varGen "a") (ExpFunctionCall () u (ExpValue () u $ ValVariable "f")- (Just $ AList () u [ Argument () u Nothing (intGen 1) ] ))) ]+ (Just $ AList () u [ Argument () u Nothing (aintGen 1) ] ))) ] {- - program Main
test/Language/Fortran/Transformation/GroupingSpec.hs view
@@ -5,39 +5,42 @@ import TestUtil import Control.Exception (evaluate) import Control.DeepSeq (force)-import Data.ByteString.Char8 (ByteString, pack)+import Data.ByteString.Char8 (pack)+import Data.Data -import Language.Fortran.Transformer+import Language.Fortran.Transformation.Monad import Language.Fortran.AST import Language.Fortran.Util.Position-import Language.Fortran.ParserMonad-import Language.Fortran.Parser.Fortran95-import Language.Fortran.Parser.Fortran77+import qualified Language.Fortran.Parser as Parser+import Language.Fortran.Parser ( Parser )+import Language.Fortran.Transformation.Grouping -groupDo :: ProgramFile () -> ProgramFile ()-groupDo = transform [ GroupLabeledDo ]-groupForall :: ProgramFile () -> ProgramFile ()-groupForall = transform [ GroupForall ]+transformWith :: Data a => Transform a () -> ProgramFile a -> ProgramFile a+transformWith = runTransform mempty mempty +groupDo', groupForall' :: Data a => ProgramFile a -> ProgramFile a+groupDo' = transformWith groupLabeledDo+groupForall' = transformWith groupForall+ spec :: Spec spec = do let name = Just "name" let endName = Just "endName" describe "Block FORALL statements" $ do it "groups unlabelled FORALL blocks" $- groupForall (exampleForall Nothing Nothing) `shouldBe'` expectedForall Nothing+ groupForall' (exampleForall Nothing Nothing) `shouldBe'` expectedForall Nothing it "groups unlabelled FORALL blocks" $- groupForall (exampleForall name name) `shouldBe'` expectedForall name+ groupForall' (exampleForall name name) `shouldBe'` expectedForall name it "groups unlabelled FORALL blocks" $ do- let lhs = (evaluate . force) (groupForall $ exampleForall name endName)+ let lhs = (evaluate . force) (groupForall' $ exampleForall name endName) lhs `shouldThrow` anyErrorCall describe "Block DO statements" $ do it "do group example1" $- groupDo example1do `shouldBe` expectedExample1do+ groupDo' example1do `shouldBe` expectedExample1do it "do group example2 with common end-point" $- groupDo example2do `shouldBe` expectedExample2do+ groupDo' example2do `shouldBe` expectedExample2do describe "Block SrcSpan's" $ do it "Spans all a BlIf" $@@ -127,20 +130,24 @@ [ ] label20 ] -getSingleParsedBlock :: Show b => (ByteString -> String -> ParseResult a b (ProgramFile A0)) -> String -> Block A0+getSingleParsedBlock :: Parser (ProgramFile A0) -> String -> Block A0 getSingleParsedBlock p c =- let pf = fromRight . fromParseResult $ p (pack c) "foobar.f"- ProgramFile _ ((PUSubroutine _ _ _ _ _ (b:_) _):_) = pf- in b+ case p "<unknown>" (pack c) of+ Right (ProgramFile _ ((PUSubroutine _ _ _ _ _ (b:_) _):_)) -> b+ e -> error $ show e +-- TODO Runs internal transformations, which means we aren't explicitly asking+-- for a grouping transformation. Bit weird. getSingleParsedBlock95 :: String -> Block A0-getSingleParsedBlock95 = getSingleParsedBlock fortran95Parser+getSingleParsedBlock95 = getSingleParsedBlock Parser.f95 +-- TODO Runs internal transformations, which means we aren't explicitly asking+-- for a grouping transformation. Bit weird. getSingleParsedBlock77 :: String -> Block A0-getSingleParsedBlock77 = getSingleParsedBlock fortran77Parser+getSingleParsedBlock77 = getSingleParsedBlock Parser.f77 getSingleParsedBlock77Legacy :: String -> Block A0-getSingleParsedBlock77Legacy = getSingleParsedBlock legacy77Parser+getSingleParsedBlock77Legacy = getSingleParsedBlock Parser.f77lNoTransform type SimpleSpan = (Int, Int, Int, Int)
test/Language/Fortran/Util/FirstParameterSpec.hs view
@@ -1,7 +1,3 @@-{-# LANGUAGE DeriveGeneric #-}-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE FlexibleInstances #-}- module Language.Fortran.Util.FirstParameterSpec(spec) where import Test.Hspec
test/Language/Fortran/Util/SecondParameterSpec.hs view
@@ -1,7 +1,3 @@-{-# LANGUAGE DeriveGeneric #-}-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE FlexibleInstances #-}- module Language.Fortran.Util.SecondParameterSpec(spec) where import Test.Hspec
test/TestUtil.hs view
@@ -1,6 +1,3 @@-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE MultiParamTypeClasses #-}- module TestUtil where import Test.Hspec@@ -9,7 +6,7 @@ import Language.Fortran.AST import Language.Fortran.AST.RealLit-import Language.Fortran.ParserMonad+import Language.Fortran.Version import Language.Fortran.Util.Position import Language.Fortran.Analysis@@ -20,10 +17,15 @@ u :: SrcSpan u = initSrcSpan -mi77 :: MetaInfo-mi77 = MetaInfo { miVersion = Fortran77, miFilename = "<unknown>" }-mi90 :: MetaInfo-mi90 = MetaInfo { miVersion = Fortran90, miFilename = "<unknown>" }+-- TODO Filename only gets set with transformations (defaults to the empty+-- string). @Parser.parseUnsafe@ uses @"<unknown>"@. So we have to define two+-- different versions.+--+-- Better would be to make an equality checker that ignores 'MetaInfo'.+mi77, mi77', mi90 :: MetaInfo+mi77 = MetaInfo { miVersion = Fortran77, miFilename = "" }+mi77' = MetaInfo { miVersion = Fortran77, miFilename = "<unknown>" }+mi90 = MetaInfo { miVersion = Fortran90, miFilename = "" } valTrue, valFalse :: Expression () valTrue = ExpValue () u $ ValLogical True Nothing@@ -41,6 +43,9 @@ intGen :: Integer -> Expression () intGen i = ExpValue () u $ ValInteger (show i) Nothing++aintGen :: Integer -> ArgumentExpression ()+aintGen = ArgExpr . intGen initGen :: [Expression ()] -> Expression () initGen es = ExpInitialisation () u $ fromList () es