This file is currently HTML. Colour coding has been used to distinguish grammar elements. This is easily changed as CSS has been used, and probably should be for a print version!
Version: 4 November 2002
This document attempts to define the CodeDom language. This language is abstract and has no defined concrete representation. A program in the language is represented by a tree of CodeDom objects, which corresponds to a parse tree in a compiler for a conventional language.
Some Definitions
A CodeDom generator is a translator/compiler which converts the abstract program represented by a CodeDom tree into some concrete language; such as C#, Visual Basic, or Mondrian.
A CodeDom compiler converts the abstract program into an assembly. This is usually done by first using a CodeDom generator and then compiling the resultant real language program with appropriate compiler.
A CodeDom snippet is a piece of unstructured text which may occur in the abstract program and a few defined locations where a particular kind of construct is expected. These are: a complete compilation unit; a member of type; a statement; and an expression. It is assumed that the unstructured text is an appropriate fragment of real language program text which a CodeDom generator or compiler can process as needed and insert into the generated real language program or assembly.
Background: The Definition of Concrete Languages
Concrete languages; such as C#, Ada 95, Mondrian, etc.; are usually defined using a combination a syntax description, the grammar, and a set of semantic rules. The boundary between these two is slightly fuzzy, but generally the context free part of the description is handled by the grammar while context sensitive and other semantics issues are handled by the semantic rules.
For example: The requirement that a predicate expression must be of boolean type, or that a variable must be defined before use, is usually left to the semantic rules. However the (semantic) restriction that certain kinds of expression, such as method calls, cannot occur on in certain contexts, such as the left hand side of assignments, may well be enforced by the grammar.
Concrete language grammars are often defined using BNF. A particular derivation may be represented by a derivation tree. Non-meaning changing transformations to the BNF are allowed, and this results in different derivation trees. A compiler writer uses the grammar definition to write a parser which constructs a parse tree from the input program, this parse tree need not be the same as the derivation tree but is usually similar. Compiler parse trees are often more general than the grammar allows, enabling grammatically invalid programs to be represented, as it is often easier to define them this way. However the parser guarantees that invalid parse trees are not constructed.
Derivation and parse trees for concrete languages are not standardised, grammar transformations and compiler parser tree definitions are left to the compiler writer. It is only the grammar and the semantic rules which are standardised and the same across all implementations.
The CodeDom language has no concrete representation, it is only represented as a tree of objects, the CodeDom tree. This tree corresponds to the parse tree found in a typical compiler for some concrete language. Unlike the situation with concrete languages, every compiler for CodeDom must use the same parse tree structure, as this is the only representation for CodeDom programs.
However this raises a problem for, as with most parse trees, a CodeDom tree is more general than the language and is capable of representing invalid as well as valid CodeDom programs. In this document we define a BNF grammar for CodeDom to provide a formal definition of what CodeDom trees are valid.
A BNF for Describing CodeDom Trees
A derivation in our BNF grammar may be represented by a derivation tree, this tree is a (small) super-set of the CodeDom parse tree.
BNF is not usually used to describe the structure of a tree (but rather the concrete language from which a tree may be formed). A rule in BNF may correspond to a node in the parse tree in some compiler, but this correspondence is not shown in the BNF. Other rules may not be represented at all in the final parse tree, being there only to assist the parsing process. While yet other rules may all be represented by the same type of node in the parse tree, which is often the reason why the trees are more general than the grammar.
This approach does not work well for CodeDom as the tree is central, it is the CodeDom language. We have defined additions to BNF to describe the linkage between the grammar and the nodes of the parse tree. In particular rules which correspond to particular node types are distinguished and the elements of a rule which correspond to node fields are labelled.
In addition to this CodeDom is actually a collection of abstract languages: a CodeDom Core language and a number of additions to the Core. Additions can be combined in any reasonable manner, though not all possible 1048576 permutations probably make sense Again we have defined extensions to BNF to describe these extensions.
Finally there is a CodeDom Subset; which is the CodeDom Core and some additional semantic restrictions.
Our BNF core syntax is a typical EBNF (Extended BNF) with syntax for alternatives and repetition:
Expression Non-terminal BASE Terminal ::= Rule definition, LHS is a non-terminal. RHS is a sequence of terminals and/or non-terminals with choice and repetition defined using the following syntax: ? Zero or one of the preceding element
Implementation note: in the CodeDom tree zero is represented by a null value* Zero or more of the preceding element + One or more of the preceding element ( ) Grouping // precede a comment
For the CodeDom language it is the parse tree structure and not the concrete language which is defined. We extend BNF to reflect the details of this tree.
If a grammar rule directly corresponds to a tree node then the non-terminal is distinguished to indicate this:
CodeCompileUnit non-terminal rule where non-terminal is a CodeDom class or a CLR type If an element of a rule corresponds to a field of a node then the element is labelled with the field name:
FieldName: precedes a rule element If element labels occur in a rule which does not correspond to a tree node then the rule defines part of a tree node and the elements are fields of the node defining rule(s) which refer to the rule.
For example:
Dog ::= Type:String CommonPart Bird ::= CanFly:Boolean CommonPart CommonPart ::= Legs:IntegerThese 3 rules define two tree nodes: Dog with fields Type and Legs; and Bird with fields CanFly and Legs.
Note: This use of rules to define parts, or common parts, of nodes is nothing to do with subclassing. The shared rule exists only to simplify the grammar.
The CodeDom tree is actually a tree of objects and subclassing has been used in varying ways to group node kinds into families. We define a set of conventions which relate tree node an grammar rules. The use of subclassing falls into two main categories:
Simple Family
Where a number of node rules define a family of constructs, the family is represented by its own node rule, and the members share no common attributes, then we have a simple family. This is the kind of grouping common in BNF descriptions of concrete languages.
For example:
CodeExpression ::= CodeArrayIndexerExpression | CodeBinaryOperatorExpression | CodeDelegateCreateExpression | ...The
CodeExpressiontype in CodeDom carries no (important) information of its own, there are never nodes of this type. This type is used for fields of other nodes where some kind of expression is allowed. The typesCodeArrayExpression,CodeBinaryOperatorExpressionandCodeDelegateCreateExpressionare all subtypes ofCodeExpression.Note: The list of alternatives may not included all the subtypes of the node defined by the rule.
Sharing Family
Where a number of node rules define a family of constructs, the family is represented by its own node rule, and the members have common attributes, then we have a sharing family. The shared (inherited) fields are included in the parent rule. This kind of grouping directly relates to the object nature of the CodeDom tree.
For example:
CodeTypeMember ::= Name:Ident Comments:CodeCommentStatementCollection Attributes:MemberAttributes CustomAttributes:CodeAttributeDeclarationCollection LinePragma:CodeLinePragma? ( CodeMemberField | CodeMemberMethod | ... )The
CodeTypeMembertype in CodeDom carries important information of its own shared by its subtypes. This type is used for fields of other nodes where some kind of type member is allowed. The typesCodeMemberFieldandCodeMemberMethodare all subtypes ofCodeTypeMember.Note: If the alternatives are optional then occurrences of the parent type are allowed. If one of the alternatives must be present then no instances of the parent type are possible.
Note: The list of alternatives may not included all the subtypes of the node defined by the rule.
The uses of subtyping in CodeDom do not all fall into the above simple categories. Variations include:
- Using a family node type where only a subset of the members of the family are valid. In such cases the grammar may introduce a non-node rule to represent the subset and add a note indicating that fields of this rule type are actually implemented as fields of the family type.
- Relating two node types by a parent/child relationship when logically they are both children of the same family. In the implementation this means that though the child inherits fields of the parent, none are actually used. The grammar is written to indicate this, introducing a parent non-node rule but adding a note to indicate how the CodeDom tree is actually structured.
A simple enumeration is represented with by a type rule with alternatives for each enumeration value.
For example, a boolean type might be defined by the rule:
Boolean ::= True | FalseFor flag enumerations, where a single enumeration value may consist of one of more enumeration constants, is represented by a rule with each constant being an optional element.
For example, a colour type representing combinations of primaries might be defined by the rule:
Colour ::= Red? Green? Blue?A third kind of enumeration exists which is a combination of the above two, that is the enumeration constants are grouped into sets and an enumeration value may only contain constants which come from disjoint sets. In CodeDom this kind of enumeration is also represented by a flag enumeration, without the semantic restrictions on valid values being specified. In BNF these are defined as a collection of optional element where each element is itself a collection of alternatives.
For example, the rule:
Kind ::= (Class | Interface) (Public | Private)Defines a flag enumeration type with four constants; where only one of
ClassandInterface, orPublicandPrivate, may be specified. An example of this kind of combination enumeration in CodeDom is MemberAttributes.
Unlike most traditional concrete languages CodeDom is not a single language but a whole set of them. CodeDom consists of CodeDom Core and twenty optional additions. We extend BNF to include conditional elements:
{ expr iff condition } Conditional inclusion. The expr, which is any valid BNF expression, is only in the language if condition is true. CodeDom generators indicate their ability to support the various additions through a flag enumeration GeneratorSupport, with the following constants:
Constant Supports... ArraysOfArrays Arrays of arrays. AssemblyAttributes Assembly custom attributes on CompileUnit's ChainedConstructorArguments Chained constructor arguments. ComplexExpressions Complex expressions. DeclareDelegates Delegate declarations. DeclareEnums Enumeration declarations. DeclareEvents Event declarations. DeclareInterfaces Interface declarations. DeclareValueTypes Value type declarations. EntryPointMethod Program entry point method designation. This is used when building executables. GotoStatements Goto statements. MultidimensionalArrays Referencing multidimensional arrays. Currently, the CodeDom cannot be used to instantiate multidimensional arrays. MultipleInterfaceMembers Declaration of members that implement multiple interfaces. NestedTypes Declaration of nested types. ParameterAttributes Parameter attributes. PublicStaticMembers Public static members. ReferenceParameters Reference and out parameters. ReturnTypeAttributes Return type attribute declarations. StaticConstructors Static constructors. TryCatchStatements try...catch statements. Win32Resources Compilation with Win32 resources. This ignored by generators (only used by compilers). In this grammar the GeneratorSupport enumeration constants are used as the condition value.
In addition to the CodeDom Core and its additions there is a CodeDom Subset. The CodeDom Subset is CodeDom Core with some additional semantic restrictions on CodeAttributeArgument.
Note: A CodeDom generator or compiler intended for use by ASP.NET is only required to support the CodeDom Subset.
Comments are included in the grammar. Comments start with "//" and continue to the end of the line. Comments are used to indicate the purpose of a rule and give additional information where needed.
Comments starting "// Implementation note:" provide additional information on the CodeDom tree, for example on the relationship between the rule and CodeDom node types.
The BNF grammar does not provide a complete definition of the CodeDom language, there are additional context sensitive and other semantic rules. Comments starting "// Semantic note:" provide this additional semantic information.
In general the semantics of CodeDom follows that of C#, if no semantics is given the semantics of C# should be assumed. To assist this comments starting "// C#:" provide a sample of how the CodeDom rule might be translated into C#.
// Implementation note: // CodeSnippetCompileUnit is a sub-class of CodeCompileUnit CompileUnit ::= CodeCompileUnit | CodeSnippetCompileUnit CodeCompileUnit ::= { AssemblyCustomAttribute:CodeAttributeDeclarationCollection iff AssemblyAttributes } ReferencedAssemblies:StringCollection Namespaces:CodeNamespaceCollection // C#: namespace Name { Comments Imports Types } CodeNamespace ::= Name:QualIdent Comments:CodeCommentStatementCollection Imports:CodeNamespaceImportCollection Types:CodeTypeDeclarationCollection // C#: using Namespace // Semantic note: // For CodeDom Core these are informational only, all references // will be fully qualified. Therefore no code needs to be // generated if only supporting CodeDom Core. CodeNamespaceImport ::= Namespace:QualIdent LinePragma:CodeLinePragma?
// A type declaration for a class, structure, interface, // delegate or enumeration. // Implementation note: // CodeTypeDelegate is a sub-class of CodeTypeDeclaration // TypeKind is represented by 4 booleans CodeTypeDeclaration ::= ( TypeDeclaration | { CodeTypeDelegate iff DeclareDelegates } ) // C#: // Attributes TypeAttributes Kind Name [: BaseTypes] { Members } // where // Kind is class, enum, interface or struct TypeDeclaration ::= BaseTypes:CodeTypeReferenceCollection TypeAttributes:TypeAttributes Members:CodeTypeMemberCollection TypeKind // Implementation note: // TypeKind is represented by four booleans: IsClass, IsEnum, IsInterface, IsStruct TypeKind ::= Class | { Enum iff DeclareEnums } | { Interface iff DeclareInterfaces } | { Struct iff DeclareValueTypes } // C#: Attributes TypeAttributes delegate ReturnType Name ( Parameters ) ; CodeTypeDelegate ::= TypeAttributes:TypeAttributes Parameters:CodeParameterDeclarationExpressionCollection ReturnType:CodeTypeReference
// Includes fields, methods, properties, constructors and nested types. // Semantic note: // If in an Enum may only contain Static CodeMemberFields CodeTypeMember ::= Name:Ident Comments:CodeCommentStatementCollection Attributes:MemberAttributes CustomAttributes:CodeAttributeDeclarationCollection LinePragma:CodeLinePragma? ( { CodeMemberEvent iff DeclareEvents } | CodeMemberField | CodeMemberMethod | CodeMemberProperty | CodeSnippetTypeMember | { CodeTypeDeclaration iff NestedTypes } ) // C#: CustomAttributes Attributes event [PrivateImplementationType.]Type Name // Semantic notes: // ImplementationTypes must be length 1 unless MultipleInterfaceMembers supported // Attributes only present/used if PrivateImplementationType not. // Attributes may only contain AccessAttributes. CodeMemberEvent ::= Type:CodeTypeReference ( ImplementationTypes:CodeTypeReferenceCollection | PrivateImplementationType:CodeTypeReference )? // C#: // CustomAttributes Name , // when of member of an Enum // CustomAttributes Name = InitExpression , // when of member of an Enum and InitExpression present // CustomAttributes Attributes Type Name ; // when of member of an Class or Struct // CustomAttributes Attributes Type Name = InitExpression ; // when of member of an Class or Struct and InitExpression present // Semantic note: // Attributes may only contain AccessAttributes, New, Const and Static. // Attributes may only contain Static if PublicStaticMembers supported. CodeMemberField ::= Type:CodeTypeReference InitExpression:CoreExpression? // Semantic note: // ImplementationTypes must be length 1 unless MultipleInterfaceMembers supported // Attributes may only contain AccessAttributes, New, Overide, Overloaded, // Abstract, Final and Static. // Attributes may only contain Static if PublicStaticMembers supported. CodeMemberMethod ::= Parameters:CodeParameterDeclarationExpressionCollection ReturnType:CodeTypeReference { ReturnTypeCustomAttributes:CodeAttributeDeclarationCollection iff ReturnTypeAttributes } ( ImplementationTypes:CodeTypeReferenceCollection | PrivateImplementationType:CodeTypeReference )? Statements:CodeStatementCollection ( CodeConstructor | { CodeEntryPointMethod iff EntryPointMethod } | { CodeTypeConstructor iff StaticConstructors } )? // Parameter declaration for a method, property, or constructor. // Semantic notes: // Direction must be In unless ReferenceParameters supported. // Type must not be an array or a single dimension array of non-array elements. // unless MultiDimensionalArrays and/or ArraysOfArrays supported. CodeParameterDeclarationExpression ::= Name:Ident Type:CodeTypeReference Direction:FieldDirection { CustomAttributes:CodeAttributeDeclarationCollection iff ParameterAttributes } // Represents a declaration for a property of a class. // Semantic note: // ImplementationTypes must be length 1 unless MultipleInterfaceMembers supported // Attributes may only contain AccessAttributes, New, Overide, Overloaded, // Abstract, Final and Static. // Attributes may only contain Static if PublicStaticMembers supported. CodeMemberProperty ::= Type:CodeTypeReference ( ImplementationTypes:CodeTypeReferenceCollection | PrivateImplementationType:CodeTypeReference )? Parameters:CodeParameterDeclarationExpressionCollection HasGet:Boolean GetStatements:CodeStatementCollection HasSet:Boolean SetStatements:CodeStatementCollection // Represents the declaration of an instance constructor for a type. CodeConstructor ::= BaseConstructorArgs:CoreArgumentCollection { ChainedConstructorArgs:CoreArgumentCollection iff ChainedConstructorArguments } // Represents the entry point of an executable. CodeEntryPointMethod ::= empty // Represents a static constructor for a class. CodeTypeConstructor ::= empty
// Represents a statement. // Implementation note: // This is a base class for other code statement objects that is never // instantiated directly (but it is not abstract). CodeStatement ::= LinePragma:CodeLinePragma? ( CodeAssignStatement | CodeAttachEventStatement | CodeCommentStatement | CodeConditionStatement | CodeExpressionStatement | { CodeGotoStatement iff GotoStatements } | CodeIternationStatement | { CodeLabeledStatement iff GotoStatements } | CodeMethodReturnStatement | CodeRemoveEventStatement | CodeSnippetStatement | CodeThrowExceptionStatement | { CodeTryCatchFinallyStatement iff TryCatchStatements } | CodeVariableDeclarationStatement ) // C#: // Left = Right when inside CodeIterationStatement // Left = Right ; otherwise CodeAssignStatement ::= Left:CoreExpression Right:CodeExpression // Attach an event handler // C#: Event += Listener ; CodeAttachEventStatement ::= Event:CodeEventReferenceExpression Listener:CoreExpression // A single comment // C#: /* Comment */ CodeCommentStatement ::= Comment:CodeComment // Conditional branch // C#: // if(Condition) { TrueStatements } // or // if(Condition) { TrueStatements } else { FalseStatements } // Semantic note: // Condition must be of type Boolean CodeConditionStatement ::= Condition:CoreExpression FalseStatements:CodeStatementCollection TrueStatements:CodeStatementCollection // A statement that consists of a single expression // C#: // Expression when inside CodeIterationStatement // Expression ; otherwise CodeExpressionStatement ::= Expression:CodeExpression // C#: goto Label ; CodeGotoStatement ::= Label:Ident // C# semantics iteration loop // C#: for(InitStatement ; TestExpression ; IncrementStatement) { Statements } // Semantic note: // TestExpression must be of type Boolean CodeIterationStatement ::= InitStatement:IterationElement TestExpression:CoreExpression IncrementStatement:IterationElement Statements:CodeStatementCollection // Implementation note: // IterationElement node fields are typed CodeStatement IterationElement ::= CodeAssignStatement | CodeExpressionStatement | { CodeVariableDeclarationStatement iff ComplexExpressions } // C#: // Label : Statement // Label : CodeLabeledStatement ::= Label:Ident Statement:CodeStatement? // C#: // return ; // return Expression ; CodeMethodReturnStatement ::= Expression:CodeExpression? // C#: Event -= Listener ; CodeRemoveEventStatement ::= Event:CodeEventReferenceExpression Listener:CoreExpression // C#: // throw ; // throw ToThrow ; CodeThrowExceptionStatement ::= ToThrow:CodeExpression? // C#: // try { TryStatements } CatchClauses // try { TryStatements } CatchClauses finally { FinallyStatements } CodeTryCatchFinallyStatement ::= TryStatements:CodeStatementCollection CatchClauses:CodeCatchClauseCollection FinallyStatements:CodeStatementCollection? // C#: catch(CatchExceptionType LocalName) { Statements } CodeCatchClause ::= CatchExceptionType:CodeTypeReference LocalName:Ident Statements:CodeStatementCollection // C#: // Type Name when inside CodeIterationStatement // Type Name = InitExpression when inside CodeIterationStatement // Type Name ; otherwise // Type Name = InitExpression; otherwise // Semantic notes: // May not occur inside a CodeConditionalStatement or CodeIterationStatement // unless ComplexExpressions supported. // "Inside" means in the body or control parts of these constructs. CodeVariableDeclarationStatement ::= Type:CodeTypeReference Name:Ident InitExpression:CodeExpression?
// Represents a code expression. // Implementation note: // This is a base class for other code expression objects and is never instantiated directly. CodeExpression ::= BasicExpression | ComplexExpression // CodeDom Core simple expressions // Implementation note: // CoreExpression fields are typed as CodeExpression CoreExpression ::= BasicExpression | { ComplexExpression iff ComplexExpressions } // CodeDom Core expressions // Implementation note: // All are subclasses of CodeExpression BasicExpression ::= CodeArgumentReferenceExpression | CodeArrayCreateExpression | CodeArgumentReferenceExpression | CodeBaseReferenceExpression | CodeCastExpression | CodeFieldReferenceExpression | CodeObjectCreateExpression | CodePrimitiveExpression | CodePropertyReference | CodeThisReferenceExpression | CodeTypeOfExpression | CodeTypeReferenceExpression | CodeVariableReferenceExpression // CodeDom complex expressions // Implementation note: // All are subclasses of CodeExpression ComplexExpression ::= CodeArrayIndexerExpression | CodeBinaryOperatorExpression | CodeDelegateCreateExpression | CodeDelegateInvokeExpression | CodeIndexerExpression | CodeMethodInvokeExpression | CodeSetValueReferenceExpression | CodeSnippetExpression // C#: ParameterName CodeArgumentReferenceExpression ::= ParameterName:Ident // C#: // Case 1a: new CreateType { Initialisers }, when CreateType is an array type // Case 1b: new CreateType[] { Initialisers }, otherwise // Case 2: new CreateType[SizeExpression] // Case 3: new CreateType[Size] // // Semantic note: // CreateType must be a single dimension array type // (CodeDom does not suppport multi-dimension array creates). // Allowance: CreateType may be non-array type, in which // case array of same type is assumed. // Initializers cannot include CodeArrayCreateExpressions unless // ArrayOfArrays is supported. CodeArrayCreateExpression ::= CreateType:CodeTypeReference ( Initializers:CoreExpressionCollection | SizeExpression:CoreExpression? | Size:Integer ) // C#: TargetObject[Indicies] // Semantic note: // Indicies must be one element unless MultidimensionalArrays are supported. CodeArrayIndexerExpression ::= Indicies:CoreExpressionCollection TargetObject:CoreExpression // C#: base // Semantic note: // May only be used in an overriding method, property or event // to call the overridden bass class method, property or event CodeBaseReferenceExpression ::= Base // C#: ( Left Operator Right ) // Semantic note: // Left and Right must be be of type Byte, Int16, Int32, Int64, // Single, Double, Char, or for operator Add only, String unless // ComplexExpressions are supported. CodeBinaryOperatorExpression ::= Left:CoreExpression Operator:CodeBinaryOperatorType Right:CoreExpression // C#: ( (TargetType) (Expression) ) // Semantic note: // TargetType must not require calling an implicit or explicit conversion operator. CodeCastExpression ::= TargetType:CodeTypeReference Expression:CoreExpression // C#: new DelegateType(TargetObject.MethodName) CodeDelegateCreateExpression ::= DelegateType:CodeTypeReference MethodName:Ident TargetObject:CoreExpression // C#: TargetObject(Parameters) CodeDelegateInvokeExpression ::= TargetObject:CoreExpression Parameters:CoreArgumentCollection // C#: TargetObject.FieldName CodeFieldReferenceExpression ::= TargetObject:CoreExpression FieldName:Ident // A reference to an indexer property of an object // C#: TargetObject[Indicies] // Semantic note: // Indicies of length 1 unless MultidimensionalArrays CodeIndexerExpression ::= TargetObject:CoreExpression Indicies:CoreExpressionCollection // C#: Method(Parameters) CodeMethodInvokeExpression ::= Method:CodeMethodReferenceExpression Parameters:CoreArgumentCollection // C#: new CreateType(Parameters) CodeObjectCreateExpression ::= CreateType:CodeTypeReference Parameters:CoreArgumentCollection // A primitive data type value // C#: // null or literal representation of value // Implementatation note: // Value field is typed Object CodePrimitiveExpression ::= Value: ( NULL | Char | Byte | Int16 | Int32 | Int64 | Single | Double | Boolean ) // C#: TargetObject.PropertyName CodePropertyReferenceExpression ::= TargetObject:CoreExpression PropertyName:Ident // The value argument of a property set method call within a property set method declaration // C#: value CodePropertySetValueReferenceExpression ::= Value // A typeof expression, an expression that returns a specified runtime type // C#: typeof(Type) CodeTypeOfExpression ::= Type:CodeTypeReference // A reference to a data type // C#: Type CodeTypeReferenceExpression ::= Type:CodeTypeReference // C#: this CodeThisReferenceExpression ::= This // A local variable // C#: VariableName CodeVariableReferenceExpression ::= VariableName:Ident
// Implementation notes: // ArgumentCollection fields are typed CodeExpressionCollection // CodeDirectionExpression is a subclass of CodeExpression ArgumentCollection ::= Argument* CoreArgumentCollection ::= CoreArgument* Argument ::= CodeExpression | { CodeDirectionExpression iff ReferenceParameters } CoreArgument ::= CoreExpression // C#: [out | ref] Expression // Implementation note: // Expression is typed CodeExpression CodeDirectionExpression ::= Direction:FieldDirection Expression: ( CodeArgumentReferenceExpression | CodeFieldReferenceExpression | CodeVariableReferenceExpression )
// C#: TargetObject.EventName // Implementation note: // CodeEventReferenceExpression is a subclass of CodeExpression CodeEventReferenceExpression ::= TargetObject:CoreExpression EventName:Ident // C#: TargetObject.MethodName // Implementation note: // CodeMethodReference is a subclass of CodeExpression CodeMethodReferenceExpression ::= TargetObject:CoreExpression MethodName:Ident // Represents a data type to CodeDom objects. // Semantic notes: // BaseType must be the fully qualified name of a non-array, // non-pointer type. // ArrayRank must be zero or one unless MultidimensionalArrays are supported. // ArrayElementType must be null, or Byte, Int16, Int32, Int64, // Single, Double, or Char, if ArrayRank is one unless ArrayofArrays are // supported. CodeTypeReference ::= BaseType:QualIdent // This is the name of the type! (NOT its base class) ArrayRank:Integer ArrayElementType:CodeTypeReference?
// A complete literal compilation unit // C#: dump Value CodeSnippetCompileUnit ::= Value:String // A literal expression fragment of type acceptable as argument to Write method // C#: dump Value CodeSnippetExpression ::= Value:String // A statement fragment, multiple statements allowed // C#: dump Value CodeSnippetStatement ::= Value:String // A member of a class, multiple members allowed // C#: dump Text CodeSnippetTypeMember ::= Text:String
// Represents an argument used in a metadata custom attribute declaration. // Semantic note: // Name should not be used for CodeDom Subset. // Value must be of type Byte, Int16, Int32, Int64, // Single, Double, Char, String, System.Type or an enumeration constant // for CodeDom Subset. CodeAttributeArgument ::= Name:Ident Value:CoreExpression // Represents an attribute declaration. CodeAttributeDeclaration ::= Name:QualIdent Arguments:CodeAttributeArgumentCollection
// Represents a comment. CodeComment ::= DocComment:Boolean Text:String // Represents a specific location within a specific file. CodeLinePragma ::= FileName:String LineNumber:Integer
These only exist as seperate productions as the CodeDom object implementation uses seperate classes for them.
// Implementation note: // CoreExpressionCollection fields are typed CodeExpressionCollection CodeAttributeArgumentCollection ::= CodeAttributeArgument* CodeAttributeDeclarationCollection ::= CodeAttributeDeclaration* CodeCatchClauseCollection ::= CodeCatchClause* CodeCommentStatementCollection ::= CodeCommentStatement* CodeExpressionCollection ::= CodeExpression* CoreExpressionCollection ::= CoreExpression* CodeNamespaceCollection ::= CodeNamespace* CodeNamespaceImportCollection ::= CodeNamespaceImport* CodeParameterDeclarationExpressionCollection ::= CodeParameterDeclarationExpression* CodeStatementCollection ::= CodeStatement* CodeTypeDeclarationCollection ::= CodeTypeDeclaration* CodeTypeMemberCollection ::= CodeTypeMember* CodeTypeReferenceCollection ::= CodeTypeReference* StringCollection ::= String*
// Specifies identifiers for supported binary operators. CodeBinaryOperatorType ::= Add | BitwiseAnd | BitwiseOr | BooleanAnd | BooleanOr | Divide | GreaterThan | GreaterThanOrEqual | IdentityEquality | IdentityInequality | LessThan | LessThanOrEqual | Modulus | Multiply | Subtract | ValueEquality | { Assign iff ComplexExpressions } // Specifies identifiers used to indicate the direction // of parameter and argument declarations. FieldDirection ::= In | Out | Ref // Specifies member attribute identifiers for class members. // Implementation note: // This is a flag enumeration // Semantic note: // There is no "virtual" scope value as this is the assumed default. The value Final // means "not virtual". So "virtual" is implied by the lack of all other scope values. MemberAttributes ::= ScopeAttributes? AccessAttributes? New? // C#: new Overloaded? // C#: nothing ScopeAttributes ::= Abstract // C#: abstract | Const // C#: const | Final // C#: nothing (means "not virtual") | Override // C#: override | Static // C#: static AccessAttributes ::= Assembly // C#: internal | Family // C#: protected | FamilyAndAssembly // C#: /* FamANDAssem */ internal | FamilyOrAssembly // C#: protected internal | Private // C#: private | Public // C#: public // Implementation note: // TypeAttributes is a type from System.Reflection. // Only a subset of its values are used by CodeDom. TypeAttributes ::= Abstract? | Class? | Interface? | NestedPrivate? | NestedPublic? | NotPublic? | Public? | Sealed?
// Implementation note: // Identifier fields are typed String Identifier ::= IDChar+ // Implementation note: // QualIdent fields are typed String QualIdent ::= Identifier ( DOT Identifier )*
// In the CodeDom implementation these are of course CLR types Integer ::= (0|1|2|3|4|5|6|7|8|9)+ String ::= Char* Char ::= any valid character IDChar ::= any valid identifier character Boolean ::= True | False