Clean Clean Clean Clean Clean


Appendix A

Context-Free Syntax Description

In this appendix the context-free syntax of CLEAN is given. Notice that the layout rule (see 2.3.3) permits the omission of the semi-colon (';') which ends a definition and of the braces ('{' and '}') which are used to group a list of definitions.

The following notational conventions are used in the context-free syntax descriptions:

[notion]means that the presence of notion is optional
{notion}means that notion can occur zero or more times
{notion}+means that notion occurs at least once
{notion}-listmeans one or more occurrences of notion separated by commas
terminalsare printed in 9 pts courier bold brown
keywordsare printed in 9 pts courier bold red
terminalsthat can be left out in layout mode are printed in 9 pts courier bold blue
{notion}/ strmeans the longest expression not containing the string str

A.1 Clean Program

CleanProgram={Module}+
Module=DefinitionModule
|ImplementationModule
DefinitionModule=definition module ModuleName ;
{DefDefinition}
|system module ModuleName ;
{DefDefinition}
ImplementationModule=[implementation] module ModuleName ;
{ImplDefinition}

ImplDefinition=ImportDef// see A.2
|FunctionDef// see A.3
|GraphDef// see A.3
|MacroDef// see A.4
|TypeDef// see A.5
|ClassDef// see A.6
|GenericsDef// see A.7
|ForeignExportDef// see A.8

DefDefinition=ImportDef// see A.2
|FunctionExportTypeDef// see A.3
|MacroDef// see A.4
|TypeDef// see A.5
|ClassExportDef// see A.6
|GenericExportDef// see A.7

A.2 Import Definition

ImportDef=ImplicitImportDef
|ExplicitImportDef

ImplicitImportDef=import [qualified] {ModuleName}-list ;

ExplicitImportDef=from ModuleName import [qualified] {Imports}-list ;
Imports=FunctionName
|::TypeName [ConstructorsOrFields]
|class ClassName [Members]
|instance ClassName {SimpleType}+
|generic FunctionName

ConstructorsOrFields=(..)
|({ConstructorName}-list)
|{..}
|{{FieldName}-list}
Members=(..)
|({MemberName}-list)

A.3 Function Definition

FunctionDef=[FunctionTypeDef]
DefOfFunction

DefOfFunction={FunctionAltDef ;}+
|ABCCodeFunctionDef
FunctionAltDef=Function {Pattern}
{GuardAlt} {LetBeforeExpression} FunctionResult
[LocalFunctionAltDefs]
FunctionResult==[>] FunctionBody
|| Guard GuardRhs
GuardAlt={LetBeforeExpression} | BooleanExpr GuardRhs
GuardRhs={GuardAlt} {LetBeforeExpression} = [>] FunctionBody
|{GuardAlt} {LetBeforeExpression} | otherwise GuardRhs

Function=FunctionName
|(FunctionName)

LetBeforeExpression=# {GraphDefOrUpdate}+
|#!{GraphDefOrUpdate}+
GraphDefOrUpdate=GraphDef
|Variable & {FieldName {Selection} = GraphExpr}-list ;
|Variable & {ArrayIndex {Selection} = GraphExpr}-list [\\ {Qualifier}-list] ;

GraphDef=Selector =[:] GraphExpr ;
Selector=BrackPattern

Guard=BooleanExpr
|otherwise
BooleanExpr=GraphExpr

FunctionBody=RootExpression ;
[LocalFunctionDefs]

RootExpression=GraphExpr

LocalFunctionAltDefs=[where] { {LocalDef}+ }
LocalDef=GraphDef
|FunctionDef
LocalFunctionDefs=[with] { {LocalDef}+ }

ABCCodeFunctionDef=Function {Pattern} = code [inline] { ABCInstructions }

A.3.1 Types of Functions

FunctionTypeDef=FunctionName :: FunctionType ;
|(FunctionName) [FixPrec] [:: FunctionType] ;
FunctionType=[{ArgType}+ ->] Type [ClassContext] [UnqTypeUnEqualities]
ClassContext=| ClassConstraints {& ClassConstraints}
ClassConstraints=ClassOrGenericName-list {SimpleType}+
UnqTypeUnEqualities=[ {{UniqueTypeVariable}+ <= UniqueTypeVariable}-list ]
ClassOrGenericName=QClassName
|FunctionName {|TypeKind|}

FunctionExportTypeDef=FunctionName :: FunctionType [Special] ;
|(FunctionName) [FixPrec] :: FunctionType [Special] ;

A.3.2 Patterns

Pattern=[Variable =:] BrackPattern
BrackPattern=PatternVariable
|QConstructor
|(GraphPattern)
|SpecialPattern
|DynamicPattern

PatternVariable=Variable
|_

QConstructor=QConstructorName
|(QConstructorName)

GraphPattern=QConstructor {Pattern}
|GraphPattern QConstructorName GraphPattern
|Pattern

SpecialPattern=BasicValuePattern
|ListPattern
|TuplePattern
|ArrayPattern
|RecordPattern
|UnitPattern

BasicValuePattern=BasicValue
BasicValue=IntDenotation// see B.4
|RealDenotation// see B.4
|BoolDenotation// see B.4
|CharDenotation// see B.4

ListPattern=[[ListKind][{LGraphPattern}-list [: GraphPattern]] [SpineStrictness]]
ListKind=!// head strict list
|#// head strict, unboxed list
||// overloaded list
SpineStrictness=!// tail (spine) strict list
LGraphPattern=GraphPattern
|CharsDenotation// see B.4

TuplePattern=(GraphPattern,{GraphPattern}-list)

RecordPattern={[QTypeName |] {FieldName [= GraphPattern]}-list}

ArrayPattern={{GraphPattern}-list}
|{{ArrayIndex = Variable}-list}
|StringDenotation

UnitPattern=()

DynamicPattern=(GraphPattern :: DynamicType)
DynamicType=[UnivQuantVariables] {DynPatternType}+ [ClassContext]
DynPatternType=Type
|TypePatternVariable
|OverloadedTypePatternVariable
TypePatternVariable=Variable
OverloadedTypeVariable=Variable^

A.3.3 Graph Expressions

GraphExpr=Application

Application={BrackGraph}+
|GraphExpr Operator GraphExpr
|GenericAppExpr
Operator=QFunctionName// see A.9
|QConstructorName// see A.9

BrackGraph=GraphVariable
|QConstructor
|QFunction
|(GraphExpr)
|LambdaAbstr
|CaseExpr
|LetExpression
|SpecialExpression
|DynamicExpression
|MatchesPatternExpr

GraphVariable=Variable// see A.9
|SelectorVariable// see A.9

QFunction=QFunctionName// see A.9
|(QFunctionName)// see A.9

LambdaAbstr=\ {Pattern}+ {LambdaGuardAlt} {LetBeforeExpression} LambdaResult
LambdaResult== GraphExpr
|-> GraphExpr
|| Guard LambdaGuardRhs
LambdaGuardAlt={LetBeforeExpression} | BooleanExpr LambdaGuardRhs
LambdaGuardRhs={LambdaGuardAlt} {LetBeforeExpression} LambdaGuardResult
LambdaGuardResult== GraphExpr
|-> GraphExpr
|| otherwise LambdaGuardRhs

CaseExpr=case GraphExpr of
{ {CaseAltDef}+ }
|if BrackGraph BrackGraph BrackGraph
CaseAltDef={Pattern}
{CaseGuardAlt} {LetBeforeExpression} CaseResult
[LocalFunctionAltDefs]
CaseResult== [>] FunctionBody
|-> FunctionBody
|| Guard CaseGuardRhs
CaseGuardAlt={LetBeforeExpression} | BooleanExpr CaseGuardRhs
CaseGuardRhs={CaseGuardAlt} {LetBeforeExpression} CaseGuardResult
CaseGuardResult== [>] FunctionBody
|-> FunctionBody
|| otherwise CaseGuardRhs

LetExpression=let { {LocalDef}+ } in GraphExpr

SpecialExpression=BasicValue
|List
|Tuple
|Array
|ArraySelection
|Record
|RecordSelection
|UnitConstructor

List=ListDenotation
|DotDotExpression
|ZF-expression
ListDenotation=[[ListKind] [{LGraphExpr}-list [: GraphExpr]] [SpineStrictness] ]
LGraphExpr=GraphExpr
|CharsDenotation// see B.4
DotDotExpression=[[ListKind] GraphExpr [,GraphExpr]..[GraphExpr] [SpineStrictness] ]
ZF-expression=[[ListKind] GraphExpr \\ {Qualifier}-list [SpineStrictness]]

Qualifier=Generators {, let { {LocalDef}+ } } {|Guard}
Generators=Generator {& Generator}
Generator=Selector <- ListExpr// select from a lazy list
|Selector <|- ListExpr// select from an overloaded list
|Selector <-: ArrayExpr// select from an array
Selector=BrackPattern// for brack patterns see 3.2
ListExpr=GraphExpr
ArrayExpr=GraphExpr

Tuple=(GraphExpr,{GraphExpr}-list)

Array=ArrayDenotation
|ArrayUpdate
|ArrayComprehension
|ArraySelection
ArrayDenotation={[ArrayKind] {GraphExpr}-list}
|StringDenotation// see B.4
ArrayUpdate={ ArrayExpr & {ArrayIndex {Selection} = GraphExpr}-list [\\ {Qualifier}-list]}
ArrayComprehension={[ArrayKind] GraphExpr \\ {Qualifier}-list}
ArraySelection= ArrayExpr.ArrayIndex {Selection}
| ArrayExpr!ArrayIndex {Selection}
Selection=.FieldName
|.ArrayIndex
ArrayExpr=GraphExpr
ArrayIndex=[{IntegerExpr}-list]
IntegerExpr=GraphExpr

Record=RecordDenotation
|RecordUpdate
RecordDenotation={[QTypeName|] {FieldName = GraphExpr}-list]}
RecordUpdate={[QTypeName|][RecordExpr &][{FieldName {Selection} = GraphExpr}-list]}
RecordExpr=GraphExpr
RecordSelection=RecordExpr [.QTypeName].FieldName {Selection}
|RecordExpr [.QTypeName]!FieldName {Selection}

UnitConstructor=()

DynamicExpression=dynamic GraphExpr [:: [UnivQuantVariables] Type [ClassContext]]

MatchesPatternExpr=GraphExpr =: QConstructorName { _ }
|GraphExpr =: BrackPattern

A.4 Macro Definition

MacroDef=[MacroFixityDef]
DefOfMacro
MacroFixityDef=(FunctionName) [FixPrec] ;
DefOfMacro=Function {Variable} :== FunctionBody ;
[LocalFunctionAltDefs]

A.5 Type Definition

TypeDef=AlgebraicTypeDef
|RecordTypeDef
|SynonymTypeDef
|AbstractTypeDef
|AbstractSynonymTypeDef
|ExtensibleAlgebraicTypeDef
|AlgebraicTypeDefExtension
|NewTypeDef

AlgebraicTypeDef=::TypeLhs= ConstructorDef
{| ConstructorDef} ;
ConstructorDef=[ExistQuantVariables] ConstructorName {ArgType} {& ClassConstraints}
|[ExistQuantVariables] (ConstructorName) [FixPrec] {ArgType} {& ClassConstraints}

TypeLhs=[*] TypeConstructor {[*]TypeVariable}
TypeConstructor=TypeName// see A.9

ExistQuantVariables=E.{TypeVariable }+:

FixPrec=infixl [Prec]
|infixr [Prec]
|infix [Prec]
Prec=Digit// see A.9

BrackType=[Strict] [UnqTypeAttrib] SimpleType

Strict=!

UnqTypeAttrib=*
|UniqueTypeVariable:// see A.9
|.

Type={BrackType}+
ArgType=BrackType
|[Strict] [UnqTypeAttrib] (UnivQuantVariables Type [ClassContext])

UnivQuantVariables=A.{TypeVariable }+:

RecordTypeDef=::TypeLhs = [ExistQuantVariables] [Strict] {{FieldName :: FieldType}-list} ;
FieldType=[Strict] Type
|UnivQuantVariables [Strict] Type
|[Strict] [UnqTypeAttrib] (UnivQuantVariables Type)

SynonymTypeDef=::TypeLhs :== Type ;

AbstractTypeDef=:: [!][UnqOrCoercibleTypeAttrib] TypeConstructor {[*]TypeVariable};
UnqOrCoercibleTypeAttrib=*
|.

AbstractSynonymTypeDef=AbstractTypeDef (:== Type ) ;

ExtensibleAlgebraicTypeDef=::TypeLhs = {ConstructorDef |} ..;

AlgebraicTypeDefExtension=::TypeLhs | ConstructorDef {| ConstructorDef} ;

NewTypeDef=::TypeLhs =: ConstructorName SimpleType ;

A.5.1 Types Expression

SimpleType=TypeVariable// see A.9
|QTypeName
|(Type)
|PredefinedType
|PredefinedTypeConstructor

PredefinedType=BasicType
|ListType
|TupleType
|ArrayType
|ArrowType
|PredefType

BasicType=Int
|Real
|Char
|Bool

ListType=[[ListTypeKind] Type [SpineStrictness]]
ListTypeKind=!// head strict list
|#// head strict, unboxed list

TupleType=([Strict] Type,{[Strict] Type}-list)

ArrayType={[ArrayKind] Type}
ArrayKind=!// strict array
|#// unboxed array

PredefType=World// see StdWorld.dcl
|File// see StdFileIO.dcl
|String// synonym for {#Char}
|()// unit type constructor

PredefinedTypeConstructor=[]// list type constructor
|[! ]// head strict list type constructor
|[ !]// tail strict list type constructor
|[!!]// strict list type constructor
|[#]// unboxed head strict list type
|[#!]// unboxed strict list type
|({,}+)// tuple type constructor (arity >= 2)
|{}// lazy array type constructor
|{!}// strict array type constructor
|{#}// unboxed array type constructor
|(->)// arrow type constructor

A.6 Class and Instance Definitions

ClassDef=TypeClassDef
|TypeClassInstanceDef

TypeClassDef=class ClassName {[.]TypeVariable}+ [ClassContext]
[[where] { {ClassMemberDef}+ }] ;
|class FunctionName {[.]TypeVariable}+ :: FunctionType;
|class (FunctionName) [FixPrec] {[.]TypeVariable}+ :: FunctionType;

ClassMemberDef=FunctionTypeDef
[MacroDef]

TypeClassInstanceDef=instance QClassName Type+ [ClassContext]
[where] { {FunctionDef}+ } ;

ClassExportDef=TypeClassDef
|TypeClassInstanceExportDef

TypeClassInstanceExportDef=instance ClassName InstanceExportTypes ;
InstanceExportTypes={Type+ [ClassContext]}-list
|Type+ [ClassContext] [where] {{FunctionTypeDef}+ }
|Type+ [ClassContext] [Special]
Special=special {{TypeVariable = Type}-list { ; {TypeVariable = Type}-list }}

A.7 Generic Definitions

GenericsDef=GenericDef ;
|GenericCase;
|DeriveDef ;

GenericDef=generic FunctionName TypeVariable+ [GenericDependencies] :: FunctionType
GenericDependencies=| {FunctionName TypeVariable+ }-list

GenericCase=FunctionName {|GenericTypeArg|} {Pattern}+ = FunctionBody
GenericTypeArg=GenericMarkerType [of Pattern]
|TypeName
|TypeVariable
GenericMarkerType=CONS
|OBJECT
|RECORD
|FIELD

DeriveDef=derive FunctionName {DerivableType}-list
|derive class ClassName {DerivableType}-list
DerivableType=TypeName
|PredefinedTypeConstructor

GenericAppExpression=FunctionName {|TypeKind|} GraphExpr
TypeKind=*
|TypeKind -> TypeKind
|IntDenotation
|(TypeKind)
|{|TypeKind|}

GenericExportDef=GenericDef ;
|derive FunctionName {DeriveExportType [UsedGenericDependencies]}-list ;
|derive class ClassName {DerivableType}-list ;
|FunctionName {|GenericExportTypeArg|} {Pattern}+ = FunctionBody

DeriveExportType=TypeName
|GenericMarkerType [of UsedGenericInfoFields]
|PredefinedTypeConstructor
|TypeVariable
UsedGenericInfoFields={[{FieldName}-list]}
|Variable

UsedGenericDependencies=with {UsedGenericDependency}
UsedGenericDependency=Variable
|_

GenericExportTypeArg=GenericMarkerType [of Pattern]
|UNIT | PAIR | EITHER

A.8 Foreign Export Definition

ForeignExportDef=foreign export [ ccall | stdcall ] FunctionName ;

A.9 Names

ModuleName=LowerCaseId|UpperCaseId|ModuleDirectoryName . ModuleName
ModuleDirectoryName=LowerCaseId|UpperCaseId
FunctionName=LowerCaseId|UpperCaseId|SymbolId
ConstructorName=UpperCaseId|SymbolId
SelectorVariable=LowerCaseId
Variable=LowerCaseId
MacroName=LowerCaseId|UpperCaseId|SymbolId
FieldName=LowerCaseId
TypeName=UpperCaseId|SymbolId
TypeVariable=LowerCaseId
UniqueTypeVariable=LowerCaseId
ClassName=LowerCaseId|UpperCaseId|SymbolId
MemberName=LowerCaseId|UpperCaseId|SymbolId

QFunctionName=QLowerCaseId|QUpperCaseId|QSymbolId
QConstructorName=QUpperCaseId|QSymbolId
QTypeName=QUpperCaseId|QSymbolId
QClassName=QLowerCaseId|QUpperCaseId|QSymbolId