module Language.CSharp.Parser.Declaration where
import Text.Parsec hiding (Empty)
import Language.CSharp.Lexer
import Language.CSharp.Syntax
import Language.CSharp.Parser.Utility
import Language.CSharp.Parser.Statement
import Language.CSharp.Parser.Expression
import Language.CSharp.Parser.Type
import Language.CSharp.Parser.Attribute
pDeclaration :: P Declaration
pDeclaration = try pNamespace <|> TypeDeclaration <$> pTypeDeclaration
pNamespace :: P Declaration
pNamespace = do
attributes <- pGlobalAttributeSections
pToken TKWnamespace
name <- pName
declarations <- between pOCurly pCCurly (many pDeclaration)
return $ NamespaceDeclaration attributes name declarations
pTypeDeclaration :: P TypeDeclaration
pTypeDeclaration = choice
[ try pClass, try pStruct , try pInterface
, try pEnum , try pDelegate ]
pEnum :: P TypeDeclaration
pEnum = do
attributes <- pAttributeSections
modifiers <- many pEnumModifier
pToken TKWenum
name <- pIdentifier
inherits <- optionMaybe (pColon *> pIntegralType)
body <- betweenCurly pEnumBody
optional pSemi
return $ EnumTypeDeclaration attributes modifiers name inherits body
pEnumBody :: P EnumBody
pEnumBody = EnumBody <$> sepBy pEnumMemberDeclaration pComma
pEnumMemberDeclaration :: P EnumMemberDeclaration
pEnumMemberDeclaration =
EnumMemberDeclaration <$> pIdentifier <*> optionMaybe (pEqualSign *> pExpression)
pEnumModifier :: P Modifier
pEnumModifier = choice [ New <$ pToken TKWnew
, Public <$ pToken TKWpublic
, Protected <$ pToken TKWprotected
, Internal <$ pToken TKWinternal
, Private <$ pToken TKWprivate ]
pStruct :: P TypeDeclaration
pStruct = do
attributes <- pAttributeSections
modifiers <- (++) <$> many pStructModifier <*> pOptionPartial
pToken TKWstruct
name <- pIdentifier
typeParams <- option [] pTypeParameters
inherits <- option [] (pColon *> sepBy1 pTypeName pComma)
constraints <- many pTypeParameterConstraintClause
body <- between pOCurly pCCurly pStructBody
optional pSemi
return $ StructTypeDeclaration attributes modifiers name typeParams inherits constraints body
pStructBody :: P StructBody
pStructBody = StructBody <$> many pMemberDeclaration
pStructModifier :: P Modifier
pStructModifier = choice [ New <$ pToken TKWnew
, Public <$ pToken TKWpublic
, Protected <$ pToken TKWprotected
, Internal <$ pToken TKWinternal
, Private <$ pToken TKWprivate ]
pDelegate :: P TypeDeclaration
pDelegate = do
attributes <- pAttributeSections
modifiers <- many pDelegateModifier
pToken TKWdelegate
ty <- pTypeWithVoid
name <- pIdentifier
typeParams <- pVariantTypeParameters
params <- betweenParens pFormalParams
constraints <- many pTypeParameterConstraintClause
pSemi
return $ DelegateTypeDeclaration attributes modifiers ty name typeParams params constraints
pDelegateModifier :: P Modifier
pDelegateModifier = choice
[ New <$ pToken TKWnew
, Public <$ pToken TKWpublic
, Protected <$ pToken TKWprotected
, Internal <$ pToken TKWinternal
, Private <$ pToken TKWprivate ]
pInterface :: P TypeDeclaration
pInterface = do
attributes <- pAttributeSections
modifiers <- (++) <$> many pInterfaceModifier <*> pOptionPartial
pToken TKWinterface
name <- pIdentifier
typeParams <- option [] pVariantTypeParameters
inherits <- option [] (pColon *> sepBy1 pTypeName pComma)
constraints <- many pTypeParameterConstraintClause
body <- pInterfaceBody
optional pSemi
return $ InterfaceTypeDeclaration attributes modifiers name typeParams inherits constraints body
pInterfaceBody :: P InterfaceBody
pInterfaceBody = InterfaceBody <$> betweenCurly (many pInterfaceMemberDeclaration)
pInterfaceMemberDeclaration :: P InterfaceMemberDeclaration
pInterfaceMemberDeclaration = choice
[ try pInterfaceMethodMemberDeclaration
, try pInterfacePropertyMemberDeclaration
, try pInterfaceEventMemberDeclaration
, pInterfaceIndexerMemberDeclaration ]
pInterfaceMethodMemberDeclaration :: P InterfaceMemberDeclaration
pInterfaceMethodMemberDeclaration = do
attributes <- pAttributeSections
modifiers <- option [] ([New] <$ pToken TKWnew)
ty <- pTypeWithVoid
name <- pIdentifier
typeParams <- option [] pTypeParameters
params <- betweenParens pFormalParams
constraints <- many pTypeParameterConstraintClause
pSemi
return $ InterfaceMethodMemberDeclaration attributes modifiers ty name typeParams params constraints
pInterfacePropertyMemberDeclaration :: P InterfaceMemberDeclaration
pInterfacePropertyMemberDeclaration = do
attributes <- pAttributeSections
modifiers <- option [] ([New] <$ pToken TKWnew)
ty <- pType
name <- pIdentifier
(accessor1, accessor2) <- betweenCurly (eitherOrBoth (try pGetInterfaceAccessor) (try pSetInterfaceAccessor))
return $ InterfacePropertyMemberDeclaration attributes modifiers ty name accessor1 accessor2
pInterfaceEventMemberDeclaration :: P InterfaceMemberDeclaration
pInterfaceEventMemberDeclaration = do
attributes <- pAttributeSections
modifiers <- option [] ([New] <$ pToken TKWnew)
pToken TKWevent
ty <- pType
name <- pIdentifier
pSemi
return $ InterfaceEventMemberDeclaration attributes modifiers ty name
pInterfaceIndexerMemberDeclaration :: P InterfaceMemberDeclaration
pInterfaceIndexerMemberDeclaration = do
attributes <- pAttributeSections
modifiers <- option [] ([New] <$ pToken TKWnew)
ty <- pType
pToken TKWthis
params <- betweenSquare pFormalParams
(accessor1, accessor2) <- betweenCurly (eitherOrBoth (try pGetInterfaceAccessor) (try pSetInterfaceAccessor))
return $ InterfaceIndexerMemberDeclaration attributes modifiers ty params accessor1 accessor2
pGetInterfaceAccessor :: P InterfaceAccessor
pGetInterfaceAccessor =
GetInterfaceAccessor <$> pAttributeSections <* pIdentifierKeyword "get" <* pSemi
pSetInterfaceAccessor :: P InterfaceAccessor
pSetInterfaceAccessor =
SetInterfaceAccessor <$> pAttributeSections <* pIdentifierKeyword "set" <* pSemi
pInterfaceModifier :: P Modifier
pInterfaceModifier = choice
[ New <$ pToken TKWnew , Public <$ pToken TKWpublic
, Protected <$ pToken TKWprotected, Internal <$ pToken TKWinternal
, Private <$ pToken TKWprivate ]
pClass :: P TypeDeclaration
pClass = do
attributes <- pAttributeSections
modifiers <- (++) <$> many pClassModifier <*> pOptionPartial
pToken TKWclass
name <- pIdentifier
typeParams <- option [] pTypeParameters
inherits <- option [] (pColon *> sepBy1 pTypeName pComma)
constraints <- many pTypeParameterConstraintClause
body <- between pOCurly pCCurly pClassBody
optional pSemi
return $ ClassTypeDeclaration attributes modifiers name typeParams inherits constraints body
pClassModifier :: P Modifier
pClassModifier = choice
[ New <$ pToken TKWnew , Public <$ pToken TKWpublic
, Protected <$ pToken TKWprotected, Internal <$ pToken TKWinternal
, Private <$ pToken TKWprivate , Abstract <$ pToken TKWabstract
, Sealed <$ pToken TKWsealed , Static <$ pToken TKWstatic ]
pClassBody :: P ClassBody
pClassBody = ClassBody <$> many pMemberDeclaration
pMemberDeclaration :: P MemberDeclaration
pMemberDeclaration = choice [ try pFieldDeclaration
, try pMethodDeclaration
, try pConstructorDeclaration
, try pDestructorDeclaration
, try pPropertyDeclaration
, try pIndexerDeclaration
, try pOperatorDeclaration
, TypeMemberDeclaration <$> pTypeDeclaration ]
pFieldDeclaration :: P MemberDeclaration
pFieldDeclaration = do
attributes <- pAttributeSections
modifiers <- (++) <$> many pFieldModifier <*> option [] ([Const] <$ pToken TKWconst)
ty <- pType
declarators <- sepBy1 pVariableDeclarator pComma
pSemi
return $ FieldMemberDeclaration attributes modifiers ty declarators
pFieldModifier :: P Modifier
pFieldModifier = choice [ New <$ pToken TKWnew
, Public <$ pToken TKWpublic
, Protected <$ pToken TKWprotected
, Internal <$ pToken TKWinternal
, Private <$ pToken TKWprivate
, Static <$ pToken TKWstatic
, Readonly <$ pToken TKWreadonly
, Volatile <$ pToken TKWvolatile ]
pPropertyDeclaration :: P MemberDeclaration
pPropertyDeclaration = do
attributes <- pAttributeSections
modifiers <- many pPropertyModifier
ty <- pType
name <- pName
body <- pPropertyLambda <|> pPropertyBody
return $ PropertyMemberDeclaration attributes modifiers ty name body
pPropertyLambda :: P PropertyBody
pPropertyLambda = PropertyLambda <$ pLambda <*> pExpression <* pSemi
pPropertyBody :: P PropertyBody
pPropertyBody = do
(accessor1, accessor2) <- betweenCurly (eitherOrBoth pPropertyGetAccessor pPropertySetAccessor)
initializer <- optionMaybe (pEqualSign *> pVariableInitializer <* pSemi)
return $ PropertyBody accessor1 accessor2 initializer
pPropertyGetAccessor :: P AccessorDeclaration
pPropertyGetAccessor = do
attributes <- pAttributeSections
modifiers <- pPropertyAccessorModifiers
pIdentifierKeyword "get"
body <- Nothing <$ pSemi <|> Just <$> betweenCurly pStatements
return $ GetAccessorDeclaration attributes modifiers body
pPropertySetAccessor :: P AccessorDeclaration
pPropertySetAccessor = do
attributes <- pAttributeSections
modifiers <- pPropertyAccessorModifiers
pIdentifierKeyword "set"
body <- Nothing <$ pSemi <|> Just <$> betweenCurly pStatements
return $ SetAccessorDeclaration attributes modifiers body
pPropertyAccessorModifiers :: P [Modifier]
pPropertyAccessorModifiers =
choice [ try ([Protected, Internal] <$ pToken TKWinternal <* pToken TKWprotected)
, try ([Internal , Protected] <$ pToken TKWprotected <* pToken TKWinternal)
, [Protected] <$ pToken TKWprotected
, [Internal] <$ pToken TKWinternal
, [Private] <$ pToken TKWprivate
, return [] ]
pPropertyModifier :: P Modifier
pPropertyModifier =
choice [ New <$ pToken TKWnew , Public <$ pToken TKWpublic
, Protected <$ pToken TKWprotected, Internal <$ pToken TKWinternal
, Private <$ pToken TKWprivate , Static <$ pToken TKWstatic
, Virtual <$ pToken TKWvirtual , Sealed <$ pToken TKWsealed
, Override <$ pToken TKWoverride , Abstract <$ pToken TKWabstract
, Extern <$ pToken TKWextern ]
pConstructorDeclaration :: P MemberDeclaration
pConstructorDeclaration = do
attributes <- pAttributeSections
modifiers <- many pConstructorModifier
name <- pIdentifier
params <- betweenParens pFormalParams
initializer <- optionMaybe (pColon *> pConstructorInitializer)
body <- ConstructorStatementBody <$> betweenCurly pStatements
return $ ConstructorMemberDeclaration attributes modifiers name params initializer body
pConstructorInitializer :: P ConstructorInitializer
pConstructorInitializer = baseCall <|> thisCall
where
baseCall = ConstructorBaseCall <$ pToken TKWbase <*> pArguments
thisCall = ConstructorThisCall <$ pToken TKWthis <*> pArguments
pConstructorModifier :: P Modifier
pConstructorModifier = choice [ Public <$ pToken TKWpublic
, Protected <$ pToken TKWprotected
, Internal <$ pToken TKWinternal
, Private <$ pToken TKWprivate
, Extern <$ pToken TKWextern ]
pDestructorDeclaration :: P MemberDeclaration
pDestructorDeclaration = do
attributes <- pAttributeSections
modifiers <- option [] ([Extern] <$ pToken TKWextern)
pToken TOpBitwiseNot
name <- pIdentifier
pOParens; pCParens
body <- DestructorStatementBody <$> betweenCurly pStatements
return $ DestructorMemberDeclaration attributes modifiers name body
pOperatorDeclaration :: P MemberDeclaration
pOperatorDeclaration = do
attributes <- pAttributeSections
modifiers <- many1 pOperatorModifier
declarator <- pOperatorDeclarator
body <- pOperatorBody
return $ OperatorMemberDeclaration attributes modifiers declarator body
pOperatorDeclarator :: P OperatorDeclarator
pOperatorDeclarator = choice
[ try $ UnaryOperatorDeclarator <$> pType
<* pToken TKWoperator
<*> pOverloadableUnaryOperator
<* pOParens
<*> pType <*> pIdentifier
<* pCParens
, try $ BinaryOperatorDeclarator <$> pType
<* pToken TKWoperator
<*> pOverloadableBinaryOperator
<* pOParens
<*> pType <*> pIdentifier
<* pComma
<*> pType <*> pIdentifier
<* pCParens
, ImplicitConversionOperatorDeclarator <$ pToken TKWimplicit
<* pToken TKWoperator
<*> pType
<* pOParens
<*> pType <*> pIdentifier
<* pCParens
, ExplicitConversionOperatorDeclarator <$ pToken TKWexplicit
<* pToken TKWoperator
<*> pType
<* pOParens
<*> pType <*> pIdentifier
<* pCParens ]
pOverloadableUnaryOperator :: P OverloadableUnaryOperator
pOverloadableUnaryOperator = choice
[ OverloadableUnaryPlus <$ pToken TOpPlus
, OverloadableUnaryMinus <$ pToken TOpMinus
, OverloadableUnaryNot <$ pToken TOpNot
, OverloadableUnaryBitwiseNot <$ pToken TOpBitwiseNot
, OverloadableUnaryPlusPlus <$ pToken TOpPlusPlus
, OverloadableUnaryMinusMinus <$ pToken TOpMinusMinus
, OverloadableUnaryTrue <$ pToken TKWtrue
, OverloadableUnaryFalse <$ pToken TKWfalse ]
pOverloadableBinaryOperator :: P BinaryOperator
pOverloadableBinaryOperator = choice
[ BinaryPlus <$ pToken TOpPlus
, BinaryMinus <$ pToken TOpMinus
, BinaryMultiply <$ pToken TOpMultiply
, BinaryDivide <$ pToken TOpDivide
, BinaryModulo <$ pToken TOpModulo
, BinaryBitwiseAnd <$ pToken TOpBitwiseAnd
, BinaryBitwiseOr <$ pToken TOpBitwiseOr
, BinaryBitwiseXor <$ pToken TOpBitwiseXor
, BinaryShiftLeft <$ pToken TOpLeftShift
, BinaryShiftRight <$ pToken TOpRightShift
, BinaryEquals <$ pToken TOpEqual
, BinaryNotEquals <$ pToken TOpNotEqual
, BinaryGreaterThan <$ pToken TOpGreaterThan
, BinaryGreaterThanEqual <$ pToken TOpGreaterThanEqual
, BinaryLessThan <$ pToken TOpLessThan
, BinaryLessThanEqual <$ pToken TOpLessThanEqual ]
pOperatorBody :: P OperatorBody
pOperatorBody = choice
[ OperatorStatementBody <$> betweenCurly pStatements
, OperatorExpressionBody <$ pLambda <*> pExpression <* pSemi
, OperatorNoBody <$ pSemi ]
pOperatorModifier :: P Modifier
pOperatorModifier = choice
[ Public <$ pToken TKWpublic
, Static <$ pToken TKWstatic
, Extern <$ pToken TKWextern ]
pEventDeclaration :: P MemberDeclaration
pEventDeclaration = do
attributes <- pAttributeSections
modifiers <- many pEventModifier
pToken TKWevent
ty <- pType
choice [ EventVariableMemberDeclaration attributes modifiers ty
<$> sepBy1 pVariableDeclarator pComma
<* pSemi
, try $ EventAccessorMemberDeclaration attributes modifiers ty
<$> pName
<* pOCurly <*> pAddEventAccessor <*> pRemoveEventAccessor
<* pCCurly
, try $ EventAccessorMemberDeclaration attributes modifiers ty
<$> pName
<* pOCurly <*> pRemoveEventAccessor <*> pAddEventAccessor
<* pCCurly ]
pAddEventAccessor :: P EventAccessor
pAddEventAccessor = do
attributes <- pAttributeSections
pIdentifierKeyword "add"
body <- betweenCurly pStatements
return $ AddEventAccessor attributes body
pRemoveEventAccessor :: P EventAccessor
pRemoveEventAccessor = do
attributes <- pAttributeSections
pIdentifierKeyword "remove"
body <- betweenCurly pStatements
return $ RemoveEventAccessor attributes body
pEventModifier :: P Modifier
pEventModifier = choice
[ New <$ pToken TKWnew , Public <$ pToken TKWpublic
, Protected <$ pToken TKWprotected, Internal <$ pToken TKWinternal
, Private <$ pToken TKWprivate , Static <$ pToken TKWstatic
, Virtual <$ pToken TKWvirtual , Sealed <$ pToken TKWsealed
, Override <$ pToken TKWoverride , Abstract <$ pToken TKWabstract
, Extern <$ pToken TKWextern ]
pIndexerDeclaration :: P MemberDeclaration
pIndexerDeclaration = do
attributes <- pAttributeSections
modifiers <- many pIndexerModifier
declarator <- pIndexerDeclarator
body <- pIndexerBody
return $ IndexerMemberDeclaration attributes modifiers declarator body
pIndexerDeclarator :: P IndexerDeclarator
pIndexerDeclarator = choice
[ try (IndexerDeclaratorThis <$> pType
<* pToken TKWthis
<*> betweenSquare pFormalParams)
, IndexerDeclaratorInterface <$> pType
<*> pInterfaceType
<* pPeriod
<* pToken TKWthis
<*> betweenSquare pFormalParams
]
pIndexerBody :: P IndexerBody
pIndexerBody = choice
[ uncurry IndexerAccessor <$> betweenCurly (eitherOrBoth pPropertyGetAccessor pPropertySetAccessor)
, IndexerLambda <$ pLambda <*> pExpression <* pSemi ]
pIndexerModifier :: P Modifier
pIndexerModifier = choice
[ New <$ pToken TKWnew , Public <$ pToken TKWpublic
, Protected <$ pToken TKWprotected, Internal <$ pToken TKWinternal
, Private <$ pToken TKWprivate , Virtual <$ pToken TKWprivate
, Sealed <$ pToken TKWprivate , Override <$ pToken TKWprivate
, Abstract <$ pToken TKWprivate , Extern <$ pToken TKWextern ]
pMethodDeclaration :: P MemberDeclaration
pMethodDeclaration = MethodMemberDeclaration
<$> pAttributeSections
<*> ((++) <$> many pMethodModifier <*> pOptionPartial)
<*> pTypeWithVoid
<*> pName
<*> option [] (betweenDiamond (sepBy1 pTypeParameter pComma))
<*> betweenParens pFormalParams
<*> many pTypeParameterConstraintClause
<*> pMethodBody
pMethodBody :: P MethodBody
pMethodBody =
MethodNoBody <$ pSemi <|>
MethodExpressionBody <$ pLambda <*> pExpression <* pSemi <|>
MethodStatementBody <$> between pOCurly pCCurly pStatements
pMethodModifier :: P Modifier
pMethodModifier = choice
[ New <$ pToken TKWnew , Public <$ pToken TKWpublic
, Protected <$ pToken TKWprotected, Internal <$ pToken TKWinternal
, Private <$ pToken TKWprivate , Static <$ pToken TKWstatic
, Virtual <$ pToken TKWvirtual , Sealed <$ pToken TKWsealed
, Override <$ pToken TKWoverride , Abstract <$ pToken TKWabstract
, Extern <$ pToken TKWextern , Async <$ pIdentifierKeyword "async" ]
pFormalParams :: P FormalParams
pFormalParams = do
params <- sepBy pFormalParam pComma
paramArray <- optionMaybe pParamArray
return $ FormalParams params paramArray
pFormalParam :: P FormalParam
pFormalParam = do
modifier <- optionMaybe pParameterModifier
ty <- pType
name <- pIdentifier
defaultArg <- optionMaybe (pEqualSign *> pExpression)
return $ FormalParam modifier ty name defaultArg
pParamArray :: P ParamArray
pParamArray = ParamArray <$ pToken TKWparams <*> pArrayType <*> pIdentifier
pParameterModifier :: P ParameterModifier
pParameterModifier =
RefParam <$ pToken TKWref <|>
OutParam <$ pToken TKWout <|>
ThisParam <$ pToken TKWthis
pOptionPartial :: P [Modifier]
pOptionPartial = option [] ([Partial] <$ pIdentifierKeyword "partial")