packages feed

fortran-src-0.10.0: src/Language/Fortran/Parser/ParserUtils.hs

{-# LANGUAGE CPP #-}

{-| Utils for various parsers (beyond token level).

We can sometimes work around there being free-form and fixed-form versions of
the @LexAction@ monad by requesting the underlying instances instances. We place
such utilities that match that form here.

-}
module Language.Fortran.Parser.ParserUtils where

import Language.Fortran.AST
import Language.Fortran.AST.Literal.Real
import Language.Fortran.AST.Literal.Complex
import Language.Fortran.Util.Position

#if !MIN_VERSION_base(4,13,0)
-- Control.Monad.Fail import is redundant since GHC 8.8.1
import Control.Monad.Fail ( MonadFail )
#endif

{- $complex-lit-parsing

Parsing complex literal parts unambiguously is a pain, so instead, we parse any
expression, then case on it to determine if it's valid for a complex literal
part -- and if so, push it into a 'ComplexPart' constructor. This may cause
unexpected behaviour if more bracketing/tuple rules are added!
-}

-- | Try to validate an expression as a COMPLEX literal part.
--
-- $complex-lit-parsing
exprToComplexLitPart :: MonadFail m => Expression a -> m (ComplexPart a)
exprToComplexLitPart e =
    case e' of
      ExpValue a ss val ->
        case val of
          ValReal    r mkp ->
            let r' = r { realLitSignificand = sign <> realLitSignificand r }
             in return $ ComplexPartReal a ss r' mkp
          ValInteger i mkp -> return $ ComplexPartInt a ss (sign<>i) mkp
          ValVariable var  -> return $ ComplexPartNamed a ss var
          _                -> fail $ "Invalid COMPLEX literal @ " <> show ss
      _ -> fail $ "Invalid COMPLEX literal @ " <> show (getSpan e')
  where
    (sign, e') = case e of ExpUnary _ _ Minus e'' -> ("-", e'')
                           ExpUnary _ _ Plus  e'' -> ("", e'')
                           _                      -> ("", e)

-- | Helper for forming COMPLEX literals.
complexLit
    :: MonadFail m => SrcSpan -> Expression A0 -> Expression A0
    -> m (Expression A0)
complexLit ss e1 e2 = do
    compReal <- exprToComplexLitPart e1
    compImag <- exprToComplexLitPart e2
    return $ ExpValue () ss $ ValComplex $ ComplexLit () ss compReal compImag