packages feed

polyglot-0.1.1.0: src/Parsers/Haskell/ClassDef.hs

module Parsers.Haskell.ClassDef where

import SyntaxTrees.Haskell.ClassDef (ClassDef (..), DerivingDef (..),
                                     InstanceDef (..))
import SyntaxTrees.Haskell.Type     (ClassConstraint)

import Parsers.Haskell.Common (class')
import Parsers.Haskell.FnDef  (fnDefOrSig, withinContext)
import Parsers.Haskell.Type   (anyKindedType, classConstraints, type',
                               typeParam)

import Bookhound.Parser            (Parser, withError)
import Bookhound.ParserCombinators (IsMatch (is), (<|>), (|*), (|+), (|?))

import Data.Foldable               (Foldable (fold))
import SyntaxTrees.Haskell.DataDef (DerivingStrategy (..))


classDef :: Parser ClassDef
classDef = withError "Class declaration" $
  ClassDef <$> (is "class" *> classConstraints')
           <*> class'
           <*> (typeParam |*)
           <* is "where"
           <*> withinContext fnDefOrSig


instanceDef :: Parser InstanceDef
instanceDef = withError "Instance declaration" $
  InstanceDef <$> (is "instance" *> classConstraints')
              <*> class'
              <*> (anyKindedType |+)
              <* is "where"
              <*> withinContext fnDefOrSig

derivingDef :: Parser DerivingDef
derivingDef = withError "Standalone deriving declaration" $
  DerivingDef <$> (is "deriving" *>
                   derivingStrategy <* is "instance")
              <*> classConstraints'
              <*> class'
              <*> (anyKindedType |+)
              <*> ((is "via" *> class') |?)

derivingStrategy :: Parser DerivingStrategy
derivingStrategy = (StandardDeriving <$ is "stock")
                   <|> (NewTypeDeriving <$ is "newtype")
                   <|> (AnyClassDeriving <$ is "anyclass")
                   <|> pure StandardDeriving


classConstraints' :: Parser [ClassConstraint]
classConstraints' = fold <$>
                    ((classConstraints type' <* is "=>") |?)