Пример #1
0
        protected void EmitEventAccessor(EventDeclaration e, VariableInitializer evtVar, bool add)
        {
            string name = evtVar.Name;

            this.Write(add ? "add" : "remove", name, " : ");
            this.WriteFunction();
            this.WriteOpenParentheses();
            this.Write("value");
            this.WriteCloseParentheses();
            this.WriteSpace();
            this.BeginBlock();
            this.WriteThis();
            this.WriteDot();
            this.Write(this.Emitter.GetEntityName(e));
            this.Write(" = ");
            this.Write(Bridge.Translator.Emitter.ROOT, ".", add ? Bridge.Translator.Emitter.DELEGATE_COMBINE : Bridge.Translator.Emitter.DELEGATE_REMOVE);
            this.WriteOpenParentheses();
            this.WriteThis();
            this.WriteDot();
            this.Write(this.Emitter.GetEntityName(e));
            this.WriteComma();
            this.WriteSpace();
            this.Write("value");
            this.WriteCloseParentheses();
            this.WriteSemiColon();
            this.WriteNewLine();
            this.EndBlock();
        }
		/// <summary>
		/// Adds the elements of an array to the end of this EventDeclarationCollection.
		/// </summary>
		/// <param name="items">
		/// The array whose elements are to be added to the end of this EventDeclarationCollection.
		/// </param>
		public virtual void AddRange(EventDeclaration[] items)
		{
			foreach (EventDeclaration item in items)
			{
				this.List.Add(item);
			}
		}
        public void CSharpAddRemoveEventDeclarationTest()
        {
            EventDeclaration ed = ParseUtilCSharp.ParseTypeMember <EventDeclaration>("event System.EventHandler MyEvent { add { } remove { } }");

            Assert.AreEqual("MyEvent", ed.Name);
            Assert.AreEqual("System.EventHandler", ed.TypeReference.Type);

            Assert.IsTrue(ed.HasAddRegion);
            Assert.IsTrue(ed.HasRemoveRegion);
        }
Пример #4
0
 void HandleVisitorEventDeclarationVisited(EventDeclaration node, InspectionData data)
 {
     foreach (var rule in policy.Rules)
     {
         if (rule.CheckEvent(node, data))
         {
             return;
         }
     }
 }
        private string GetSignature(EventDeclaration member)
        {
            var signature = member.Accessibility == Accessibility.Implicit ? string.Empty : member.Accessibility.ToString();

            signature += " Event " + member.IdentifierName + "(";

            var selectedParams = Parameters.Select(s => s.Name);

            return(signature + string.Join(", ", selectedParams) + ")");
        }
Пример #6
0
        public static OverloadsCollection Create(IEmitter emitter, EventDeclaration eventDeclaration)
        {
            string key = eventDeclaration.GetHashCode().ToString();
            if (emitter.OverloadsCache.ContainsKey(key))
            {
                return emitter.OverloadsCache[key];
            }

            return new OverloadsCollection(emitter, eventDeclaration);
        }
        public override IUnresolvedEntity VisitEventDeclaration(EventDeclaration node)
        {
            var ev = (IUnresolvedEvent)base.VisitEventDeclaration(node);

            //if (ev.AddAccessor != null)
            //    ev.AddAccessor.Declaration = node.AddAccessor;
            //if (ev.RemoveAccessor != null)
            //    ev.RemoveAccessor.Declaration = node.RemoveAccessor;
            return(SetDecl(ev, node));
        }
        public EventReferenceExpression(Expression target,EventDeclaration _event)
        {
            if (target==null)
                throw new ArgumentNullException("target");
            if (_event==null)
                throw new ArgumentNullException("_event");

            this.target = target;
            this.declaringEvent = _event;
        }
        public void Equality_DifferentType()
        {
            var a = new EventDeclaration {
                Name = SomeEvent
            };
            var b = new EventDeclaration();

            Assert.AreNotEqual(a, b);
            Assert.AreNotEqual(a.GetHashCode(), b.GetHashCode());
        }
Пример #10
0
        public static OverloadsCollection Create(IEmitter emitter, EventDeclaration eventDeclaration)
        {
            string key = eventDeclaration.GetHashCode().ToString();

            if (emitter.OverloadsCache.ContainsKey(key))
            {
                return(emitter.OverloadsCache[key]);
            }

            return(new OverloadsCollection(emitter, eventDeclaration));
        }
Пример #11
0
 public override void VisitEventDeclaration(EventDeclaration eventDeclaration)
 {
     if (CheckModifiers(eventDeclaration) && !_ignoredMembers.Contains(eventDeclaration.Name))
     {
         foreach (var v in eventDeclaration.Variables)
         {
             _currentMembers.Peek().Item2.Add(new NameNode(v.Name, v));
         }
     }
     base.VisitEventDeclaration(eventDeclaration);
 }
Пример #12
0
 public override void VisitEventDeclaration(EventDeclaration eventDeclaration)
 {
     if (eventDeclaration.IsPublic())
     {
         base.VisitEventDeclaration(eventDeclaration);
     }
     else
     {
         eventDeclaration.Remove();
     }
 }
Пример #13
0
 public static DeclarationExecuter Build(Declaration declaration)
 {
     return(declaration switch
     {
         DefineDeclaration define => new DefineDeclarationExecuter(define),
         VariableDeclaration variable => new VariableDeclarationExecuter(variable),
         SoundsDeclaration sounds => new SoundsDeclarationExecuter(sounds),
         ActionDeclaration action => new ActionDeclarationExecuter(action),
         EventDeclaration evt => new EventDeclarationExecuter(evt),
         _ => ErrorHelper.ThrowUnknownNode <DeclarationExecuter>(declaration)
     });
Пример #14
0
        public static OverloadsCollection Create(IEmitter emitter, EventDeclaration eventDeclaration)
        {
            OverloadsCollection collection;

            if (emitter.Cache.TryGetNode(eventDeclaration, false, out collection))
            {
                return(collection);
            }

            return(new OverloadsCollection(emitter, eventDeclaration));
        }
Пример #15
0
        public static OverloadsCollection Create(IEmitter emitter, EventDeclaration eventDeclaration)
        {
            var key = new Tuple <AstNode, bool>(eventDeclaration, false);

            if (emitter.OverloadsCacheNodes.ContainsKey(key))
            {
                return(emitter.OverloadsCacheNodes[key]);
            }

            return(new OverloadsCollection(emitter, eventDeclaration));
        }
Пример #16
0
 public override void VisitEventDeclaration(EventDeclaration eventDeclaration)
 {
     currentMember = eventDeclaration.GetSymbol() as IMember;
     if (currentMember == null)
     {
         return;
     }
     SetContext();
     base.VisitEventDeclaration(eventDeclaration);
     currentMember = null;
 }
Пример #17
0
        public EventDetailsViewModel(EventViewModel parent)
            : base(parent)
        {
            _projectEvent = Parent.ProjectEvent;

            _eventDecl = Parent.Event;
            _isVisibleOutsideAssembly = _eventDecl.IsVisibleOutsideAssembly();

            _parentProperties = new NodeProperties();
            _parentProperties.LoadParent(Parent);
        }
        public void Equality_ReallyEquals()
        {
            var a = new EventDeclaration {
                Name = SomeEvent
            };
            var b = new EventDeclaration {
                Name = SomeEvent
            };

            Assert.AreEqual(a, b);
            Assert.AreEqual(a.GetHashCode(), b.GetHashCode());
        }
        EventDeclaration TransformAutomaticEvents(CustomEventDeclaration ev)
        {
            if (!ev.PrivateImplementationType.IsNull)
            {
                return(null);
            }
            if (!ev.Modifiers.HasFlag(Modifiers.Abstract))
            {
                if (!CheckAutomaticEventV4(ev) && !CheckAutomaticEventV2(ev) && !CheckAutomaticEventV4MCS(ev))
                {
                    return(null);
                }
            }
            RemoveCompilerGeneratedAttribute(ev.AddAccessor.Attributes, attributeTypesToRemoveFromAutoEvents);
            EventDeclaration ed = new EventDeclaration();

            ev.Attributes.MoveTo(ed.Attributes);
            foreach (var attr in ev.AddAccessor.Attributes)
            {
                attr.AttributeTarget = "method";
                ed.Attributes.Add(attr.Detach());
            }
            ed.ReturnType = ev.ReturnType.Detach();
            ed.Modifiers  = ev.Modifiers;
            ed.Variables.Add(new VariableInitializer(ev.Name));
            ed.CopyAnnotationsFrom(ev);

            IEvent eventDef = ev.GetSymbol() as IEvent;

            if (eventDef != null)
            {
                IField field = eventDef.DeclaringType.GetFields(f => f.Name == ev.Name, GetMemberOptions.IgnoreInheritedMembers).SingleOrDefault();
                if (field != null)
                {
                    ed.AddAnnotation(field);
                    var attributes = field.GetAttributes()
                                     .Where(a => !attributeTypesToRemoveFromAutoEvents.Contains(a.AttributeType.FullName))
                                     .Select(context.TypeSystemAstBuilder.ConvertAttribute).ToArray();
                    if (attributes.Length > 0)
                    {
                        var section = new AttributeSection {
                            AttributeTarget = "field"
                        };
                        section.Attributes.AddRange(attributes);
                        ed.Attributes.Add(section);
                    }
                }
            }

            ev.ReplaceWith(ed);
            return(ed);
        }
Пример #20
0
 private OverloadsCollection(IEmitter emitter, EventDeclaration eventDeclaration)
 {
     this.Emitter        = emitter;
     this.Name           = emitter.GetEventName(eventDeclaration);
     this.JsName         = this.Emitter.GetEntityName(eventDeclaration, false, true);
     this.Inherit        = !eventDeclaration.HasModifier(Modifiers.Static);
     this.Static         = eventDeclaration.HasModifier(Modifiers.Static);
     this.Member         = this.FindMember(eventDeclaration);
     this.TypeDefinition = this.Member.DeclaringTypeDefinition;
     this.Type           = this.Member.DeclaringType;
     this.InitMembers();
     //this.Emitter.OverloadsCache[eventDeclaration.GetHashCode().ToString()] = this;
 }
Пример #21
0
        public EventViewModel FindEvent(EventDeclaration eventDecl)
        {
            var type = eventDecl.GetOwnerType();

            var typeViewModel = FindType(type);

            if (typeViewModel == null)
            {
                return(null);
            }

            return(typeViewModel.FindEvent(eventDecl));
        }
Пример #22
0
 private OverloadsCollection(IEmitter emitter, EventDeclaration eventDeclaration)
 {
     this.Emitter        = emitter;
     this.Name           = emitter.GetEventName(eventDeclaration);
     this.JsName         = this.Emitter.GetEntityName(eventDeclaration);
     this.Inherit        = !eventDeclaration.HasModifier(Modifiers.Static);
     this.Static         = eventDeclaration.HasModifier(Modifiers.Static);
     this.Member         = this.FindMember(eventDeclaration);
     this.TypeDefinition = this.Member.DeclaringTypeDefinition;
     this.Type           = this.Member.DeclaringType;
     this.InitMembers();
     this.Emitter.Cache.AddNode(eventDeclaration, false, this);
 }
Пример #23
0
        public EventDeclarationExecuter(EventDeclaration declaration) : base(declaration)
        {
            if (declaration.ActionName != null)
            {
                actionName = declaration.ActionName;
            }
            else if (declaration.ActionDeclaration != null)
            {
                actionDeclaration = new ActionDeclarationExecuter(declaration.ActionDeclaration);
            }

            evt = EventDeclaratorExecuter.Build(declaration.Event);
        }
        public void CSharpEventImplementingInterfaceDeclarationTest()
        {
            EventDeclaration ed = ParseUtilCSharp.ParseTypeMember <EventDeclaration>("event EventHandler MyInterface.MyEvent;");

            Assert.AreEqual("MyEvent", ed.Name);
            Assert.AreEqual("EventHandler", ed.TypeReference.Type);

            Assert.IsFalse(ed.HasAddRegion);
            Assert.IsFalse(ed.HasRemoveRegion);

            Assert.AreEqual("MyInterface", ed.InterfaceImplementations[0].InterfaceType.Type);
            Assert.AreEqual("MyEvent", ed.InterfaceImplementations[0].MemberName);
        }
Пример #25
0
 public override void VisitEventDeclaration(EventDeclaration d)
 {
     if (d.Modifiers.HasFlag(Modifiers.Private) || d.Modifiers.HasFlag(Modifiers.Internal) ||
         d.Modifiers.HasFlag(Modifiers.Override))
     {
         d.Remove();
     }
     else
     {
         RemoveAttributes(d.Attributes);
         base.VisitEventDeclaration(d);
     }
 }
Пример #26
0
        public UnifiedElement VisitEventDeclaration(
            EventDeclaration eventDeclaration, object data)
        {
            var names =
                eventDeclaration.Variables.Select(prop => prop.Name.ToVariableIdentifier())
                .ToSet <UnifiedIdentifier>();

            return(UnifiedEventDefinition.Create(
                       annotations: null,
                       modifiers: LookupModifiers(eventDeclaration.Modifiers),
                       type: LookupType(eventDeclaration.ReturnType),
                       names: names));
        }
Пример #27
0
 private void CompileAndAddAutoEventMethodsToType(JsClass jsClass, EventDeclaration node, IEvent evt, EventScriptSemantics options, string backingFieldName)
 {
     if (options.AddMethod != null && options.AddMethod.GeneratedMethodName != null)
     {
         var compiled = CreateMethodCompiler().CompileAutoEventAdder(evt, options, backingFieldName);
         AddCompiledMethodToType(jsClass, evt.AddAccessor, options.AddMethod, new JsMethod(evt.AddAccessor, options.AddMethod.GeneratedMethodName, new string[0], compiled));
     }
     if (options.RemoveMethod != null && options.RemoveMethod.GeneratedMethodName != null)
     {
         var compiled = CreateMethodCompiler().CompileAutoEventRemover(evt, options, backingFieldName);
         AddCompiledMethodToType(jsClass, evt.RemoveAccessor, options.RemoveMethod, new JsMethod(evt.RemoveAccessor, options.RemoveMethod.GeneratedMethodName, new string[0], compiled));
     }
 }
		public static MethodDeclaration CreateEventInvocator (RefactoringContext context, TypeDeclaration declaringType, EventDeclaration eventDeclaration, VariableInitializer initializer, IMethod invokeMethod, bool useExplictType)
		{
			bool hasSenderParam = false;
			IEnumerable<IParameter> pars = invokeMethod.Parameters;
			if (invokeMethod.Parameters.Any()) {
				var first = invokeMethod.Parameters [0];
				if (first.Name == "sender" /*&& first.Type == "System.Object"*/) {
					hasSenderParam = true;
					pars = invokeMethod.Parameters.Skip(1);
				}
			}
			const string handlerName = "handler";

			var arguments = new List<Expression>();
			if (hasSenderParam)
				arguments.Add(eventDeclaration.HasModifier (Modifiers.Static) ? (Expression)new PrimitiveExpression (null) : new ThisReferenceExpression());
			bool useThisMemberReference = false;
			foreach (var par in pars) {
				arguments.Add(new IdentifierExpression(par.Name));
				useThisMemberReference |= par.Name == initializer.Name;
			}
			var proposedHandlerName = GetNameProposal(initializer);
			var modifiers = eventDeclaration.HasModifier(Modifiers.Static) ? Modifiers.Static : Modifiers.Protected | Modifiers.Virtual;
			if (declaringType.HasModifier (Modifiers.Sealed)) {
				modifiers = Modifiers.None;
			}
			var methodDeclaration = new MethodDeclaration {
				Name = proposedHandlerName,
				ReturnType = new PrimitiveType ("void"),
				Modifiers = modifiers,
				Body = new BlockStatement {
					new VariableDeclarationStatement (
						useExplictType ? eventDeclaration.ReturnType.Clone () : new PrimitiveType ("var"), handlerName, 
						useThisMemberReference ? 
						(Expression)new MemberReferenceExpression (new ThisReferenceExpression (), initializer.Name) 
						: new IdentifierExpression (initializer.Name)
						),
					new IfElseStatement {
						Condition = new BinaryOperatorExpression (new IdentifierExpression (handlerName), BinaryOperatorType.InEquality, new PrimitiveExpression (null)),
						TrueStatement = new InvocationExpression (new IdentifierExpression (handlerName), arguments)
					}
				}
			};

			foreach (var par in pars) {
				var typeName = context.CreateShortType(par.Type);
				var decl = new ParameterDeclaration(typeName, par.Name);
				methodDeclaration.Parameters.Add(decl);
			}
			return methodDeclaration;
		}
        public EventReferenceExpression(Expression target, EventDeclaration _event)
        {
            if (target == null)
            {
                throw new ArgumentNullException("target");
            }
            if (_event == null)
            {
                throw new ArgumentNullException("_event");
            }

            this.target         = target;
            this.declaringEvent = _event;
        }
Пример #30
0
 private OverloadsCollection(IEmitter emitter, EventDeclaration eventDeclaration)
 {
     this.Emitter = emitter;
     this.Name = emitter.GetEventName(eventDeclaration);
     this.JsName = this.Emitter.GetEntityName(eventDeclaration, false, true);
     this.Inherit = !eventDeclaration.HasModifier(Modifiers.Static);
     this.Static = eventDeclaration.HasModifier(Modifiers.Static);
     this.CancelChangeCase = true;
     this.Member = this.FindMember(eventDeclaration);
     this.TypeDefinition = this.Member.DeclaringTypeDefinition;
     this.Type = this.Member.DeclaringType;
     this.InitMembers();
     this.Emitter.OverloadsCache[eventDeclaration.GetHashCode().ToString()] = this;
 }
Пример #31
0
        public override object VisitEventDeclaration(EventDeclaration eventDeclaration, object data)
        {
            FixIndentation(eventDeclaration.StartLocation);
            EnforceBraceStyle(policy.EventBraceStyle, eventDeclaration.LBrace, eventDeclaration.RBrace);
            if (policy.IndentEventBody)
            {
                IndentLevel++;
            }

            if (eventDeclaration.AddAccessor != null)
            {
                FixIndentation(eventDeclaration.AddAccessor.StartLocation);
                if (eventDeclaration.AddAccessor.Body != null)
                {
                    if (!policy.AllowEventAddBlockInline || eventDeclaration.AddAccessor.Body.LBrace.StartLocation.Line != eventDeclaration.AddAccessor.Body.RBrace.StartLocation.Line)
                    {
                        EnforceBraceStyle(policy.EventAddBraceStyle, eventDeclaration.AddAccessor.Body.LBrace, eventDeclaration.AddAccessor.Body.RBrace);
                    }
                    else
                    {
                        nextStatementIndent = " ";
                    }

                    VisitBlockWithoutFixIndentation(eventDeclaration.AddAccessor.Body, policy.IndentBlocks, data);
                }
            }

            if (eventDeclaration.RemoveAccessor != null)
            {
                FixIndentation(eventDeclaration.RemoveAccessor.StartLocation);
                if (eventDeclaration.RemoveAccessor.Body != null)
                {
                    if (!policy.AllowEventRemoveBlockInline || eventDeclaration.RemoveAccessor.Body.LBrace.StartLocation.Line != eventDeclaration.RemoveAccessor.Body.RBrace.StartLocation.Line)
                    {
                        EnforceBraceStyle(policy.EventRemoveBraceStyle, eventDeclaration.RemoveAccessor.Body.LBrace, eventDeclaration.RemoveAccessor.Body.RBrace);
                    }
                    else
                    {
                        nextStatementIndent = " ";
                    }
                    VisitBlockWithoutFixIndentation(eventDeclaration.RemoveAccessor.Body, policy.IndentBlocks, data);
                }
            }

            if (policy.IndentEventBody)
            {
                IndentLevel--;
            }
            return(null);
        }
Пример #32
0
        private static void AddByRefIdentifierToHandlers(
            EventDeclaration eventDeclaration,
            int parameterIndex,
            DeclarationFinder finder,
            IRewriteSession rewriteSession)
        {
            var handlers = finder.FindEventHandlers(eventDeclaration)
                           .Select(implementation => implementation.Parameters[parameterIndex]);

            foreach (var parameter in handlers)
            {
                AddByRefIdentifier(rewriteSession, parameter);
            }
        }
Пример #33
0
 private OverloadsCollection(IEmitter emitter, EventDeclaration eventDeclaration)
 {
     this.Emitter          = emitter;
     this.Name             = emitter.GetEventName(eventDeclaration);
     this.JsName           = this.Emitter.GetEntityName(eventDeclaration, false, true);
     this.Inherit          = !eventDeclaration.HasModifier(Modifiers.Static);
     this.Static           = eventDeclaration.HasModifier(Modifiers.Static);
     this.CancelChangeCase = true;
     this.Member           = this.FindMember(eventDeclaration);
     this.TypeDefinition   = this.Member.DeclaringTypeDefinition;
     this.Type             = this.Member.DeclaringType;
     this.InitMembers();
     this.Emitter.OverloadsCacheNodes[new Tuple <AstNode, bool>(eventDeclaration, false)] = this;
 }
Пример #34
0
 public override object VisitEventDeclaration(EventDeclaration eventDeclaration, object data)
 {
     foreach (var eventVariable in eventDeclaration.Variables)
     {
         TypeDeclarations.Add(new DeclarationInfo()
         {
             Accessibility        = eventDeclaration.Modifiers.ToString(),
             DeclarationClassType = TypeDeclarationKind.Event,
             Namespace            = eventVariable.GetCurrentNamespace(),
             Name = eventVariable.Name
         });
     }
     return(base.VisitEventDeclaration(eventDeclaration, data));
 }
Пример #35
0
        public virtual string GetEventName(EventDeclaration evt)
        {
            if (!string.IsNullOrEmpty(evt.Name))
            {
                return(evt.Name);
            }

            if (evt.Variables.Count > 0)
            {
                return(evt.Variables.First().Name);
            }

            return(null);
        }
		public override object VisitEventDeclaration(EventDeclaration eventDeclaration, object data)
		{
			if (!eventDeclaration.HasAddRegion && !eventDeclaration.HasRaiseRegion && !eventDeclaration.HasRemoveRegion) {
				if (eventDeclaration.TypeReference.IsNull) {
					DelegateDeclaration dd = new DelegateDeclaration(eventDeclaration.Modifier, null);
					dd.Name = eventDeclaration.Name + "EventHandler";
					dd.Parameters = eventDeclaration.Parameters;
					dd.ReturnType = new TypeReference("System.Void", true);
					dd.Parent = eventDeclaration.Parent;
					eventDeclaration.Parameters = null;
					InsertAfterSibling(eventDeclaration, dd);
					eventDeclaration.TypeReference = new TypeReference(dd.Name);
				}
			}
			return base.VisitEventDeclaration(eventDeclaration, data);
		}
        public void CSharpMultipleEventDeclarationTest()
        {
            TypeDeclaration t = ParseUtilCSharp.ParseGlobal <TypeDeclaration>("class C { public event EventHandler A, B; }");

            Assert.AreEqual(2, t.Children.Count);

            EventDeclaration ed = (EventDeclaration)t.Children[0];

            Assert.AreEqual(Modifiers.Public, ed.Modifier);
            Assert.AreEqual("EventHandler", ed.TypeReference.Type);
            Assert.AreEqual("A", ed.Name);

            ed = (EventDeclaration)t.Children[1];
            Assert.AreEqual(Modifiers.Public, ed.Modifier);
            Assert.AreEqual("EventHandler", ed.TypeReference.Type);
            Assert.AreEqual("B", ed.Name);
        }
 protected void IntroduceEvent(TransformationContext context, TypeDefDeclaration type, EventDeclaration theEvent)
 {
     var fieldRef = type.FindField(theEvent.Name);
     FieldDefDeclaration field;
     if(fieldRef == null) {
         field = new FieldDefDeclaration {
             Attributes = FieldAttributes.Private,
             Name = theEvent.Name,
             FieldType = theEvent.EventType,
         };
         type.Fields.Add(field);
     } else {
         field = fieldRef.Field;
     }
     var addOn = theEvent.GetAccessor(MethodSemantics.AddOn);
     if (addOn == null) {
         theEvent.ImplementAddOn(type, field, AspectInfrastructureTask.WeavingHelper);
     }
     var removeOn = theEvent.GetAccessor(MethodSemantics.RemoveOn);
     if (removeOn == null) {
         theEvent.ImplementRemoveOn(type, field, AspectInfrastructureTask.WeavingHelper);
     }
 }
		protected override string GenerateCode(ITypeDefinition currentClass)
		{
			bool implementInterface = this.implementInterface.IsChecked == true;
			bool hasOnPropertyChanged = HasOnPropertyChanged(currentClass);
			bool useEventArgs = false;
			
			AstNode insertionAnchorElement = refactoringContext.GetNode();
			if ((insertionAnchorElement == null) || !(insertionAnchorElement.Parent is TypeDeclaration)) {
				return null;
			}
			NewLineNode newLineNode = insertionAnchorElement as NewLineNode;
			while (insertionAnchorElement.PrevSibling is NewLineNode)
				insertionAnchorElement = insertionAnchorElement.PrevSibling ?? insertionAnchorElement;
			
			using (Script script = refactoringContext.StartScript()) {
				TypeDeclaration currentClassDeclaration = insertionAnchorElement.Parent as TypeDeclaration;
				
				if (implementInterface && !currentClass.IsStatic) {
					if (!hasOnPropertyChanged) {
						var nodes = new List<AstNode>();
						if (!currentClass.GetAllBaseTypeDefinitions().Any(bt => bt.FullName == "System.ComponentModel.INotifyPropertyChanged")) {
							AstNode nodeBeforeClassBlock = currentClassDeclaration.LBraceToken;
							if (nodeBeforeClassBlock.PrevSibling is NewLineNode) {
								// There's a new line before the brace, insert before it!
								nodeBeforeClassBlock = nodeBeforeClassBlock.PrevSibling;
							}
							int insertion = editor.Document.GetOffset(nodeBeforeClassBlock.StartLocation);
							
							AstType interfaceTypeNode = refactoringContext.CreateShortType("System.ComponentModel", "INotifyPropertyChanged", 0);
							var directBaseTypes = currentClass.DirectBaseTypes.Where(t => t.FullName != "System.Object");
							if (currentClassDeclaration.BaseTypes.Count > 0) {
								script.InsertText(insertion, ", " + interfaceTypeNode + " ");
							} else {
								script.InsertText(insertion, " : " + interfaceTypeNode + " ");
							}
						}

						var rt = new GetClassTypeReference("System.ComponentModel", "INotifyPropertyChanged", 0);
						var rtResolved = rt.Resolve(refactoringContext.Compilation);
						var ev = rtResolved.GetEvents().First(e => e.Name == "PropertyChanged");
						
						EventDeclaration propertyChangedEvent = new EventDeclaration();
						propertyChangedEvent.Variables.Add(new VariableInitializer(ev.Name));
						propertyChangedEvent.Modifiers = Modifiers.Public;
						propertyChangedEvent.ReturnType = refactoringContext.CreateShortType(ev.ReturnType);
						
						nodes.Add(propertyChangedEvent);
						
						MethodDeclaration onEvent = CreateOnEventMethod(ev, currentClass);
						nodes.Add(onEvent);
						foreach (var node in nodes) {
							script.InsertAfter(insertionAnchorElement, node);
							AppendNewLine(script, insertionAnchorElement, newLineNode);
						}
						useEventArgs = false;
					} else {
						useEventArgs = currentClass.GetMethods().First(m => m.Name == "OnPropertyChanged").Parameters[0].Type.FullName != "System.String";
					}
				}
				
				foreach (FieldWrapper field in fields.Where(f => f.IsIncluded)) {
					var prop = CreateProperty(field.Field, true, field.AddSetter);
					if (!field.Field.IsStatic && !currentClass.IsStatic && field.AddSetter && implementInterface) {
						var invocation = new ExpressionStatement(CreateInvocation(field.PropertyName, useEventArgs));
						var assignment = prop.Setter.Body.Children.ElementAt(0) as Statement;
						prop.Setter.Body = new BlockStatement();
						BlockStatement elseBlock = new BlockStatement();
						elseBlock.Add(assignment.Clone());
						elseBlock.Add(invocation);
						prop.Setter.Body.Add(
							new IfElseStatement(
								new BinaryOperatorExpression(new IdentifierExpression(field.MemberName), BinaryOperatorType.InEquality, new IdentifierExpression("value")),
								elseBlock
							)
						);
					}
					
					script.InsertAfter(insertionAnchorElement, prop);
					AppendNewLine(script, insertionAnchorElement, newLineNode);
				}
			}
			
			return null;
		}
Пример #40
0
			public override void Visit (EventField e)
			{
				EventDeclaration newEvent = new EventDeclaration ();
				AddAttributeSection (newEvent, e);
				var location = LocationsBag.GetMemberLocation (e);
				AddModifiers (newEvent, location);
				
				if (location != null)
					newEvent.AddChild (new CSharpTokenNode (Convert (location[0]), "event".Length), EventDeclaration.Roles.Keyword);
				newEvent.AddChild (ConvertToType (e.TypeName), AstNode.Roles.Type);
				
				VariableInitializer variable = new VariableInitializer ();
				variable.AddChild (Identifier.Create (e.MemberName.Name, Convert (e.MemberName.Location)), FieldDeclaration.Roles.Identifier);
				
				if (e.Initializer != null) {
					if (location != null)
						variable.AddChild (new CSharpTokenNode (Convert (location[0]), 1), FieldDeclaration.Roles.Assign);
					variable.AddChild ((Expression)e.Initializer.Accept (this), VariableInitializer.Roles.Expression);
				}
				newEvent.AddChild (variable, FieldDeclaration.Roles.Variable);
				if (e.Declarators != null) {
					foreach (var decl in e.Declarators) {
						var declLoc = LocationsBag.GetLocations (decl);
						if (declLoc != null)
							newEvent.AddChild (new CSharpTokenNode (Convert (declLoc [0]), 1), FieldDeclaration.Roles.Comma);
						
						variable = new VariableInitializer ();
						variable.AddChild (Identifier.Create (decl.Name.Value, Convert (decl.Name.Location)), VariableInitializer.Roles.Identifier);

						if (decl.Initializer != null) {
							if (declLoc != null)
								variable.AddChild (new CSharpTokenNode (Convert (declLoc [1]), 1), FieldDeclaration.Roles.Assign);
							variable.AddChild ((Expression)decl.Initializer.Accept (this), VariableInitializer.Roles.Expression);
						}
						newEvent.AddChild (variable, FieldDeclaration.Roles.Variable);
					}
				}
				
				if (location != null)
					newEvent.AddChild (new CSharpTokenNode (Convert (location[1]), ";".Length), EventDeclaration.Roles.Semicolon);
				
				typeStack.Peek ().AddChild (newEvent, TypeDeclaration.MemberRole);
			}
Пример #41
0
 public EventDeclarationBlock(IEmitter emitter, EventDeclaration eventDeclaration)
     : base(emitter, eventDeclaration)
 {
     this.Emitter = emitter;
     this.EventDeclaration = eventDeclaration;
 }
        static void AddImplementation(RefactoringContext context, TypeDeclaration result, IType guessedType)
        {
            foreach (var property in guessedType.GetProperties ()) {
                if (!property.IsAbstract)
                    continue;
                if (property.IsIndexer) {
                    var indexerDecl = new IndexerDeclaration {
                        ReturnType = context.CreateShortType(property.ReturnType),
                        Modifiers = GetModifiers(property),
                        Name = property.Name
                    };
                    indexerDecl.Parameters.AddRange(ConvertParameters(context, property.Parameters));
                    if (property.CanGet)
                        indexerDecl.Getter = new Accessor();
                    if (property.CanSet)
                        indexerDecl.Setter = new Accessor();
                    result.AddChild(indexerDecl, Roles.TypeMemberRole);
                    continue;
                }
                var propDecl = new PropertyDeclaration {
                    ReturnType = context.CreateShortType(property.ReturnType),
                    Modifiers = GetModifiers (property),
                    Name = property.Name
                };
                if (property.CanGet)
                    propDecl.Getter = new Accessor();
                if (property.CanSet)
                    propDecl.Setter = new Accessor();
                result.AddChild(propDecl, Roles.TypeMemberRole);
            }

            foreach (var method in guessedType.GetMethods ()) {
                if (!method.IsAbstract)
                    continue;
                var decl = new MethodDeclaration {
                    ReturnType = context.CreateShortType(method.ReturnType),
                    Modifiers = GetModifiers (method),
                    Name = method.Name,
                    Body = new BlockStatement {
                        new ThrowStatement(new ObjectCreateExpression(context.CreateShortType("System", "NotImplementedException")))
                    }
                };
                decl.Parameters.AddRange(ConvertParameters(context, method.Parameters));
                result.AddChild(decl, Roles.TypeMemberRole);
            }

            foreach (var evt in guessedType.GetEvents ()) {
                if (!evt.IsAbstract)
                    continue;
                var decl = new EventDeclaration {
                    ReturnType = context.CreateShortType(evt.ReturnType),
                    Modifiers = GetModifiers (evt),
                    Variables = {
                        new VariableInitializer {
                            Name = evt.Name
                        }
                    }
                };
                decl.Variables.Add(new VariableInitializer(evt.Name));
                result.AddChild(decl, Roles.TypeMemberRole);
            }
        }
Пример #43
0
			public override void Visit (EventProperty ep)
			{
				EventDeclaration newEvent = new EventDeclaration ();
				
				var location = LocationsBag.GetMemberLocation (ep);
				AddModifiers (newEvent, location);
				
				if (location != null)
					newEvent.AddChild (new CSharpTokenNode (Convert (location[0]), "event".Length), EventDeclaration.Roles.Keyword);
				newEvent.AddChild ((INode)ep.TypeName.Accept (this), EventDeclaration.Roles.ReturnType);
				newEvent.AddChild (new Identifier (ep.MemberName.Name, Convert (ep.MemberName.Location)), EventDeclaration.Roles.Identifier);
				if (location != null)
					newEvent.AddChild (new CSharpTokenNode (Convert (location[1]), 1), EventDeclaration.Roles.LBrace);
				
				if (ep.Add != null) {
					MonoDevelop.CSharp.Dom.Accessor addAccessor = new MonoDevelop.CSharp.Dom.Accessor ();
					var addLocation = LocationsBag.GetMemberLocation (ep.Add);
					AddModifiers (addAccessor, addLocation);
					addAccessor.AddChild (new CSharpTokenNode (Convert (ep.Add.Location), "add".Length), EventDeclaration.Roles.Keyword);
					if (ep.Add.Block != null)
						addAccessor.AddChild ((INode)ep.Add.Block.Accept (this), EventDeclaration.Roles.Body);
					newEvent.AddChild (addAccessor, EventDeclaration.EventAddRole);
				}
				
				if (ep.Remove != null) {
					MonoDevelop.CSharp.Dom.Accessor removeAccessor = new MonoDevelop.CSharp.Dom.Accessor ();
					var removeLocation = LocationsBag.GetMemberLocation (ep.Remove);
					AddModifiers (removeAccessor, removeLocation);
					removeAccessor.AddChild (new CSharpTokenNode (Convert (ep.Remove.Location), "remove".Length), EventDeclaration.Roles.Keyword);
					
					if (ep.Remove.Block != null)
						removeAccessor.AddChild ((INode)ep.Remove.Block.Accept (this), EventDeclaration.Roles.Body);
					newEvent.AddChild (removeAccessor, EventDeclaration.EventRemoveRole);
				}
				if (location != null)
					newEvent.AddChild (new CSharpTokenNode (Convert (location[2]), 1), EventDeclaration.Roles.RBrace);
				
				typeStack.Peek ().AddChild (newEvent, TypeDeclaration.Roles.Member);
			}
Пример #44
0
        public override void VisitEventDeclaration(EventDeclaration eventDeclaration)
        {
            foreach (var singleEvt in eventDeclaration.Variables) {
                var resolveResult = _resolver.Resolve(singleEvt);
                if (!(resolveResult is MemberResolveResult)) {
                    _errorReporter.Region = eventDeclaration.GetRegion();
                    _errorReporter.InternalError("Event declaration " + singleEvt.Name + " does not resolve to a member.");
                    return;
                }

                var evt = ((MemberResolveResult)resolveResult).Member as IEvent;
                if (evt == null) {
                    _errorReporter.Region = eventDeclaration.GetRegion();
                    _errorReporter.InternalError("Event declaration " + singleEvt.Name + " does not resolve to an event (resolves to " + resolveResult.ToString() + ")");
                    return;
                }

                var jsClass = GetJsClass(evt.DeclaringTypeDefinition);
                if (jsClass == null)
                    return;

                var impl = _metadataImporter.GetEventSemantics(evt);
                switch (impl.Type) {
                    case EventScriptSemantics.ImplType.AddAndRemoveMethods: {
                        if ((impl.AddMethod != null && impl.AddMethod.GenerateCode) || (impl.RemoveMethod != null && impl.RemoveMethod.GenerateCode)) {
                            if (evt.IsAbstract) {
                                if (impl.AddMethod.GenerateCode)
                                    AddCompiledMethodToType(jsClass, evt.AddAccessor, impl.AddMethod, new JsMethod(evt.AddAccessor, impl.AddMethod.Name, null, null));
                                if (impl.RemoveMethod.GenerateCode)
                                    AddCompiledMethodToType(jsClass, evt.RemoveAccessor, impl.RemoveMethod, new JsMethod(evt.RemoveAccessor, impl.RemoveMethod.Name, null, null));
                            }
                            else {
                                var fieldName = _metadataImporter.GetAutoEventBackingFieldName(evt);
                                if (singleEvt.Initializer.IsNull) {
                                    AddDefaultFieldInitializerToType(jsClass, fieldName, evt, evt.ReturnType, evt.DeclaringTypeDefinition, evt.IsStatic);
                                }
                                else {
                                    CompileAndAddFieldInitializerToType(jsClass, fieldName, evt.DeclaringTypeDefinition, singleEvt.Initializer, evt.IsStatic);
                                }

                                CompileAndAddAutoEventMethodsToType(jsClass, eventDeclaration, evt, impl, fieldName);
                            }
                        }
                        break;
                    }

                    case EventScriptSemantics.ImplType.NotUsableFromScript: {
                        break;
                    }

                    default: {
                        throw new InvalidOperationException("Invalid event implementation type");
                    }
                }
            }
        }
Пример #45
0
			public override void Visit(EventField e)
			{
				var newEvent = new EventDeclaration();
				AddAttributeSection(newEvent, e);
				var location = LocationsBag.GetMemberLocation(e);
				int l = 0;
				AddModifiers(newEvent, location);
				
				if (location != null && location.Count > 0)
					newEvent.AddChild(new CSharpTokenNode(Convert(location [l++]), EventDeclaration.EventKeywordRole), EventDeclaration.EventKeywordRole);
				newEvent.AddChild(ConvertToType(e.TypeExpression), Roles.Type);
				
				var variable = new VariableInitializer();
				variable.AddChild(Identifier.Create(e.MemberName.Name, Convert(e.MemberName.Location)), Roles.Identifier);
				
				if (e.Initializer != null) {
					if (location != null && location.Count > l)
						variable.AddChild(new CSharpTokenNode(Convert(location [l++]), Roles.Assign), Roles.Assign);
					variable.AddChild((Expression)e.Initializer.Accept(this), Roles.Expression);
				}
				newEvent.AddChild(variable, Roles.Variable);
				if (e.Declarators != null) {
					foreach (var decl in e.Declarators) {
						var declLoc = LocationsBag.GetLocations(decl);
						if (declLoc != null)
							newEvent.AddChild(new CSharpTokenNode(Convert(declLoc [0]), Roles.Comma), Roles.Comma);
						
						variable = new VariableInitializer();
						variable.AddChild(Identifier.Create(decl.Name.Value, Convert(decl.Name.Location)), Roles.Identifier);

						if (decl.Initializer != null) {
							if (declLoc != null)
								variable.AddChild(new CSharpTokenNode(Convert(declLoc [1]), Roles.Assign), Roles.Assign);
							variable.AddChild((Expression)decl.Initializer.Accept(this), Roles.Expression);
						}
						newEvent.AddChild(variable, Roles.Variable);
					}
				}
				
				if (location != null && location.Count > l)
					newEvent.AddChild(new CSharpTokenNode(Convert(location [l++]), Roles.Semicolon), Roles.Semicolon);
				
				typeStack.Peek().AddChild(newEvent, Roles.TypeMemberRole);
			}
Пример #46
0
 public override void VisitEventDeclaration(EventDeclaration eventDeclaration)
 {
     bool isStatic = eventDeclaration.HasModifier(Modifiers.Static);
     foreach (var item in eventDeclaration.Variables)
     {
         Expression initializer = item.Initializer;
         this.CurrentType.EventsDeclarations.Add(item.Name, eventDeclaration);
         if (isStatic)
         {
             this.CurrentType.StaticConfig.Events.Add(new TypeConfigItem
             {
                 Name = item.Name,
                 Entity = eventDeclaration,
                 Initializer = initializer,
                 VarInitializer = item
             });
     }
     else
     {
             this.CurrentType.InstanceConfig.Events.Add(new TypeConfigItem
             {
                 Name = item.Name,
                 Entity = eventDeclaration,
                 Initializer = initializer,
                 VarInitializer = item
             });
         }
     }
 }
 public virtual void VisitEventDeclaration(EventDeclaration eventDeclaration)
 {
     if (this.ThrowException)
     {
         throw (Exception)this.CreateException(eventDeclaration);
     }
 }
Пример #48
0
        public void VisitEventDeclaration(EventDeclaration declaration)
        {
            Formatter.StartNode(declaration);

            if (declaration.CustomAttributeSections.Count > 0)
            {
                WriteNodes(declaration.CustomAttributeSections, true);
                Formatter.WriteLine();
            }

            if (declaration.ModifierElements.Count > 0)
            {
                WriteSpaceSeparatedNodes(declaration.ModifierElements);
                Formatter.WriteSpace();
            }

            Formatter.WriteKeyword("event");
            Formatter.WriteSpace();
            declaration.EventType.AcceptVisitor(this);
            Formatter.WriteSpace();
            WriteCommaSeparatedNodes(declaration.Declarators);

            if (declaration.AddAccessor == null && declaration.RemoveAccessor == null)
            {
                WriteSemicolon();
            }
            else
            {
                Formatter.OpenBrace(Parameters.EventBraceStyle);

                declaration.AddAccessor.AcceptVisitor(this);
                declaration.RemoveAccessor.AcceptVisitor(this);

                Formatter.CloseBrace(Parameters.EventBraceStyle);
            }

            Formatter.EndNode();
        }
Пример #49
0
		public override void VisitEventDeclaration(EventDeclaration eventDeclaration)
		{
			FormatAttributedNode(eventDeclaration);
			if (eventDeclaration.NextSibling is EventDeclaration && IsSimpleEvent(eventDeclaration) && IsSimpleEvent(eventDeclaration.NextSibling)) {
				EnsureBlankLinesAfter(eventDeclaration, policy.BlankLinesBetweenEventFields);
			} else if (IsMember(eventDeclaration.NextSibling)) {
				EnsureBlankLinesAfter(eventDeclaration, policy.BlankLinesBetweenMembers);
			}
			
			var lastLoc = eventDeclaration.StartLocation;
			curIndent.Push(IndentType.Block);
			foreach (var initializer in eventDeclaration.Variables) {
				if (lastLoc.Line != initializer.StartLocation.Line) {
					FixStatementIndentation(initializer.StartLocation);
					lastLoc = initializer.StartLocation;
				}
				initializer.AcceptVisitor(this);
			}
			curIndent.Pop ();
		}
Пример #50
0
 public EventTreeNode( EventDeclaration @event ) : base( @event, TreeViewImage.Event, @event.Visibility )
 {
     this.@event = @event;
     this.Text = @event.Name + " : " + @event.EventType.ToString();
     this.EnableLatePopulate();
 }
Пример #51
0
		void HandleVisitorEventDeclarationVisited (EventDeclaration node, InspectionData data)
		{
			foreach (var rule in policy.Rules) {
				if (rule.CheckEvent (node, data))
					return;
			}
		}
Пример #52
0
 private void CompileAndAddAutoEventMethodsToType(JsClass jsClass, EventDeclaration node, IEvent evt, EventScriptSemantics options, string backingFieldName)
 {
     if (options.AddMethod != null && options.AddMethod.GenerateCode) {
         var compiled = CreateMethodCompiler().CompileAutoEventAdder(evt, options, backingFieldName);
         AddCompiledMethodToType(jsClass, evt.AddAccessor, options.AddMethod, new JsMethod(evt.AddAccessor, options.AddMethod.Name, new string[0], compiled));
     }
     if (options.RemoveMethod != null && options.RemoveMethod.GenerateCode) {
         var compiled = CreateMethodCompiler().CompileAutoEventRemover(evt, options, backingFieldName);
         AddCompiledMethodToType(jsClass, evt.RemoveAccessor, options.RemoveMethod, new JsMethod(evt.RemoveAccessor, options.RemoveMethod.Name, new string[0], compiled));
     }
 }
Пример #53
0
        // IMPORTANT NOTE:
        // The grammar consists of a few LALR(1) conflicts. These issues are, however, correctly handled, due to the fact that the grammar 
        // is defined in a specific order making the already added parser actions have precedence over the other.
        //
        // Known conflicts that are correctly handled:
        //
        // - ELSE:          Shift/Reduce conflict Dangling ELSE problem.  Lots of articles are around on the internet. 
        //                  The shift action is taken here.
        //
        // - CLOSE_PARENS:  Shift/Reduce conflict. This is due to the fact that the explicit cast expression is like the parenthesized 
        //                  expression. The shift action is taken here.
        //
        // - STAR:          Reduce/Reduce conflict, between VariableType -> TypeNameExpression and PrimaryExpression -> TypeNameExpression, 
        //                  due to the fact variable types can have '*', and look therefore like a binary operator expression. 
        //                  The first reduce action is taken here.

        public CSharpGrammar()
        {
            // Please let me know if there is a better way of tidying this :s

            TokenMapping.Add((int)ERROR, Error);

            #region Definitions to use later

            var statementList = new GrammarDefinition("StatementList");
            var statementListOptional = new GrammarDefinition("StatementListOptional",
                rule: null
                      | statementList);

            var blockStatement = new GrammarDefinition("BlockStatement");

            var variableDeclarator = new GrammarDefinition("VariableDeclarator");
            var variableDeclaratorList = new GrammarDefinition("VariableDeclaratorList");
            variableDeclaratorList.Rule = variableDeclarator
                                          | variableDeclaratorList
                                          + ToElement(COMMA)
                                          + variableDeclarator;
            var variableDeclaration = new GrammarDefinition("VariableDeclaration");
            var variableInitializer = new GrammarDefinition("VariableInitializer");
            var arrayInitializer = new GrammarDefinition("ArrayInitializer");
            var arrayInitializerOptional = new GrammarDefinition("ArrayInitializerOptional",
                rule: null | arrayInitializer);
            var identifierInsideBody = new GrammarDefinition("IdentifierInsideBody",
                rule: ToElement(IDENTIFIER),
                createNode: node => ToIdentifier(node.Children[0].Result));
            var identifierInsideBodyOptional = new GrammarDefinition("IdentifierInsideBodyOptional",
                rule: null | identifierInsideBody);

            variableDeclarator.Rule = identifierInsideBody
                                      | identifierInsideBody
                                      + ToElement(EQUALS)
                                      + variableInitializer;
            variableDeclarator.ComputeResult = node =>
            {
                var result = new VariableDeclarator((Identifier) node.Children[0].Result);
                if (node.Children.Count > 1)
                {
                    result.OperatorToken = (AstToken) node.Children[1].Result;
                    result.Value = (Expression) node.Children[2].Result;
                }
                return result;
            };

            var typeReference = new GrammarDefinition("TypeReference");

            var identifierExpression = new GrammarDefinition("IdentifierExpression",
                rule: identifierInsideBody,
                createNode: node => new IdentifierExpression((Identifier) node.Children[0].Result));

            var usingDirectiveListOptional = new GrammarDefinition("UsingDirectiveListOptional");

            #endregion

            #region Type References

            var namespaceOrTypeExpression = new GrammarDefinition("NamespaceOrTypeExpression");

            namespaceOrTypeExpression.Rule = identifierExpression |
                                             namespaceOrTypeExpression
                                             + ToElement(DOT)
                                             + ToElement(IDENTIFIER);

            namespaceOrTypeExpression.ComputeResult = node =>
            {
                if (node.Children.Count == 1)
                    return ToTypeReference((IConvertibleToType) node.Children[0].Result);
                var result = new MemberTypeReference();
                result.Target = (TypeReference) node.Children[0].Result;
                result.AddChild(AstNodeTitles.Accessor, node.Children[1].Result);
                result.Identifier = ToIdentifier(node.Children[2].Result);
                return result;
            };

            ComputeResultDelegate createPrimitiveTypeExpression = node =>
            {
                if (node.Children[0].Result is PrimitiveTypeReference)
                    return node.Children[0].Result;
                return new PrimitiveTypeReference
                {
                    Identifier = ToIdentifier(node.Children[0].Result),
                    PrimitiveType = CSharpLanguage.PrimitiveTypeFromString(((AstToken) node.Children[0].Result).Value)
                };
            };

            var integralType = new GrammarDefinition("IntegralType",
                rule: ToElement(SBYTE)
                      | ToElement(BYTE)
                      | ToElement(SHORT)
                      | ToElement(USHORT)
                      | ToElement(INT)
                      | ToElement(UINT)
                      | ToElement(LONG)
                      | ToElement(ULONG)
                      | ToElement(CHAR),
                createNode: createPrimitiveTypeExpression);

            var primitiveType = new GrammarDefinition("PrimitiveTypeExpression",
                rule: ToElement(OBJECT)
                      | ToElement(STRING)
                      | ToElement(BOOL)
                      | ToElement(DECIMAL)
                      | ToElement(FLOAT)
                      | ToElement(DOUBLE)
                      | ToElement(VOID)
                      | integralType,
                createNode: createPrimitiveTypeExpression);

            var dimensionSeparators = new GrammarDefinition("DimensionSeparators");
            dimensionSeparators.Rule = ToElement(COMMA)
                                       | dimensionSeparators + ToElement(COMMA);

            var rankSpecifier = new GrammarDefinition("RankSpecifier",
                rule: ToElement(OPEN_BRACKET) + ToElement(CLOSE_BRACKET)
                      | ToElement(OPEN_BRACKET) + dimensionSeparators
                      + ToElement(CLOSE_BRACKET),
                createNode: node =>
                {
                    var result = new ArrayTypeRankSpecifier();
                    result.LeftBracket = (AstToken) node.Children[0].Result;
                    if (node.Children.Count == 3)
                    {
                        foreach (var dimensionSeparator in node.Children[1].GetAllNodesFromListDefinition()
                            .Select(x => x.Result))
                        {
                            result.Dimensions++;
                            result.AddChild(AstNodeTitles.ElementSeparator, dimensionSeparator);
                        }
                    }
                    result.RightBracket = (AstToken) node.Children[node.Children.Count - 1].Result;
                    return result;
                });

            var arrayType = new GrammarDefinition("ArrayType",
                rule: typeReference
                      + rankSpecifier,
                createNode: node => new ArrayTypeReference()
                {
                    BaseType = (TypeReference) node.Children[0].Result,
                    RankSpecifier = (ArrayTypeRankSpecifier) node.Children[1].Result
                });

            var pointerType = new GrammarDefinition("PointerType",
                rule: typeReference
                      + ToElement(STAR),
                createNode: node => new PointerTypeReference()
                {
                    BaseType = (TypeReference) node.Children[0].Result,
                    PointerToken = (AstToken) node.Children[1].Result
                });

            var typeExpression = new GrammarDefinition("TypeExpression",
                rule: namespaceOrTypeExpression
                      | primitiveType);

            typeReference.Rule = typeExpression
                                 | arrayType
                                 | pointerType
                ;

            #endregion

            #region Expressions

            ComputeResultDelegate createBinaryOperatorExpression = node =>
            {
                if (node.Children.Count == 1)
                    return node.Children[0].Result;

                var result = new BinaryOperatorExpression();
                result.Left = (Expression) node.Children[0].Result;
                var operatorToken = (AstToken) (node.Children[1].Result ?? node.Children[1].Children[0].Result);
                result.Operator = CSharpLanguage.BinaryOperatorFromString(operatorToken.Value);
                result.OperatorToken = (AstToken) operatorToken;
                result.Right = (Expression) node.Children[2].Result;
                return result;
            };

            var expression = new GrammarDefinition("Expression");
            var expressionOptional = new GrammarDefinition("ExpressionOptional",
                rule: null
                      | expression);

            var primaryExpression = new GrammarDefinition("PrimaryExpression");

            var primitiveExpression = new GrammarDefinition("PrimitiveExpression",
                rule: ToElement(LITERAL)
                      | ToElement(TRUE)
                      | ToElement(FALSE)
                      | ToElement(NULL),
                createNode: node =>
                {
                    object interpretedValue;
                    node.Children[0].Result.UserData.TryGetValue("InterpretedValue", out interpretedValue);
                    var result = new PrimitiveExpression(interpretedValue, ((AstToken) node.Children[0].Result).Value, node.Children[0].Range);
                    return result;
                });

            var parenthesizedExpression = new GrammarDefinition("ParenthesizedExpression",
                rule: ToElement(OPEN_PARENS)
                      + expression
                      + ToElement(CLOSE_PARENS)
                      | ToElement(OPEN_PARENS)
                      + Error
                      + ToElement(CLOSE_PARENS),
                createNode: node => new ParenthesizedExpression
                {
                    LeftParenthese = (AstToken) node.Children[0].Result,
                    Expression = (Expression) node.Children[1].Result,
                    RightParenthese = (AstToken) node.Children[2].Result,
                });

            var memberAccessorOperator = new GrammarDefinition("MemberAccessorOperator",
                rule: ToElement(DOT)
                      | ToElement(OP_PTR)
                      | ToElement(INTERR_OPERATOR));

            var memberReferenceExpression = new GrammarDefinition("MemberReferenceExpression",
                rule: primaryExpression + memberAccessorOperator + identifierInsideBody
                | primaryExpression + memberAccessorOperator + Error,
                createNode: node => new MemberReferenceExpression
                {
                    Target =
                        (Expression)
                            ((IConvertibleToExpression) node.Children[0].Result).ToExpression().Remove(),
                    Accessor = CSharpLanguage.AccessorFromString(((AstToken) node.Children[1].Children[0].Result).Value),
                    AccessorToken = (AstToken) node.Children[1].Children[0].Result,
                    Identifier = (Identifier) node.Children[2].Result
                });

            var argument = new GrammarDefinition("Argument",
                rule: expression
                      | ToElement(REF) + expression
                      | ToElement(OUT) + expression,
                createNode: node =>
                {
                    if (node.Children.Count > 1)
                    {
                        return new DirectionExpression()
                        {
                            DirectionToken = (AstToken) node.Children[0].Result,
                            Direction = CSharpLanguage.DirectionFromString(((AstToken) node.Children[0].Result).Value),
                            Expression = (Expression) node.Children[1].Result
                        };
                    }
                    return node.Children[0].Result;
                });

            var argumentList = new GrammarDefinition("ArgumentList");
            argumentList.Rule = argument
                                | argumentList + ToElement(COMMA) + argument;
            var argumentListOptional = new GrammarDefinition("ArgumentListOptional",
                rule: null | argumentList);

            var invocationExpression = new GrammarDefinition("InvocationExpression",
                rule: primaryExpression
                      + ToElement(OPEN_PARENS)
                      + argumentListOptional
                      + ToElement(CLOSE_PARENS),
                createNode: node =>
                {
                    var result = new InvocationExpression()
                    {
                        Target = (Expression) node.Children[0].Result,
                        LeftParenthese = (AstToken) node.Children[1].Result,
                    };

                    if (node.Children[2].HasChildren)
                    {
                        foreach (var subNode in node.Children[2].Children[0].GetAllListAstNodes())
                        {
                            if (subNode is AstToken)
                                result.AddChild(AstNodeTitles.ElementSeparator, subNode);
                            else
                                result.Arguments.Add((Expression) subNode);
                        }
                    }

                    result.RightParenthese = (AstToken) node.Children[3].Result;
                    return result;
                });

            var indexerExpression = new GrammarDefinition("IndexerExpression",
                rule: primaryExpression
                      + ToElement(OPEN_BRACKET_EXPR)
                      + argumentList
                      + ToElement(CLOSE_BRACKET),
                createNode: node =>
                {
                    var result = new IndexerExpression()
                    {
                        Target = (Expression) node.Children[0].Result,
                        LeftBracket = (AstToken) node.Children[1].Result,
                    };

                    foreach (var subNode in node.Children[2].GetAllListAstNodes())
                    {
                        if (subNode is AstToken)
                            result.AddChild(AstNodeTitles.ElementSeparator, subNode);
                        else
                            result.Indices.Add((Expression) subNode);
                    }

                    result.RightBracket = (AstToken) node.Children[3].Result;
                    return result;
                });

            var createObjectExpression = new GrammarDefinition("CreateObjectExpression",
                rule: ToElement(NEW)
                      + typeReference
                      + ToElement(OPEN_PARENS)
                      + argumentListOptional
                      + ToElement(CLOSE_PARENS)
                      + arrayInitializerOptional
                      | ToElement(NEW)
                      + namespaceOrTypeExpression
                      + arrayInitializer,
                createNode: node =>
                {
                    var result = new CreateObjectExpression();
                    result.NewKeyword = (AstToken) node.Children[0].Result;
                    result.Type = (TypeReference) node.Children[1].Result;

                    if (node.Children.Count == 6)
                    {
                        result.LeftParenthese = (AstToken) node.Children[2].Result;

                        if (node.Children[3].HasChildren)
                        {
                            foreach (var subNode in node.Children[3].Children[0].GetAllListAstNodes())
                            {
                                if (subNode is AstToken)
                                    result.AddChild(AstNodeTitles.ElementSeparator, subNode);
                                else
                                    result.Arguments.Add((Expression) subNode);
                            }
                        }

                        result.RightParenthese = (AstToken) node.Children[4].Result;
                    }

                    var initializerNode = node.Children[node.Children.Count - 1];
                    if (initializerNode.HasChildren)
                        result.Initializer = (ArrayInitializer) initializerNode.Result;
                    return result;
                });

            var createArrayExpression = new GrammarDefinition("CreateArrayExpression",
                rule: ToElement(NEW)
                      + rankSpecifier
                      + arrayInitializer
                      | ToElement(NEW)
                      + typeReference
                      + rankSpecifier
                      + arrayInitializer
                      | ToElement(NEW)
                      + typeReference
                      + ToElement(OPEN_BRACKET_EXPR)
                      + argumentList
                      + ToElement(CLOSE_BRACKET)
                      + arrayInitializerOptional
                ,
                createNode: node =>
                {
                    var result = new CreateArrayExpression();
                    result.NewKeyword = (AstToken) node.Children[0].Result;

                    switch (node.Children.Count)
                    {
                        case 3:
                            {
                                var rankSpecifierNode = (ArrayTypeRankSpecifier) node.Children[1].Result;
                                result.LeftBracket = (AstToken) rankSpecifierNode.LeftBracket.Remove();
                                result.RightBracket = (AstToken) rankSpecifierNode.RightBracket.Remove();
                                break;
                            }
                        case 4:
                            {
                                result.Type = (TypeReference) node.Children[1].Result;
                                var rankSpecifierNode = (ArrayTypeRankSpecifier) node.Children[2].Result;
                                result.LeftBracket = (AstToken) rankSpecifierNode.LeftBracket.Remove();
                                result.RightBracket = (AstToken) rankSpecifierNode.RightBracket.Remove();
                                break;
                            }
                        case 6:
                            {
                                result.Type = (TypeReference) node.Children[1].Result;
                                result.LeftBracket = (AstToken) node.Children[2].Result;
                                if (node.Children[3].HasChildren)
                                {
                                    foreach (var subNode in node.Children[3].Children[0].GetAllListAstNodes())
                                    {
                                        if (subNode is AstToken)
                                            result.AddChild(AstNodeTitles.ElementSeparator, subNode);
                                        else
                                            result.Arguments.Add((Expression) subNode);
                                    }
                                }
                                result.RightBracket = (AstToken) node.Children[4].Result;
                                break;
                            }
                    }
                    var initializerNode = node.Children[node.Children.Count - 1];
                    if (initializerNode.HasChildren)
                        result.Initializer = (ArrayInitializer) initializerNode.Result;
                    return result;
                });

            var primitiveTypeExpression = new GrammarDefinition("PrimitiveTypeExpression",
                rule: primitiveType,
                createNode: node => ((IConvertibleToExpression) node.Children[0].Result).ToExpression());

            var typeNameExpression = new GrammarDefinition("TypeNameExpression",
                rule: identifierExpression
                      | memberReferenceExpression
                      | primitiveTypeExpression);

            var thisExpression = new GrammarDefinition("ThisExpression",
                rule: ToElement(THIS),
                createNode: node => new ThisReferenceExpression()
                {
                    ThisKeywordToken = (AstToken) node.Children[0].Result,
                });

            var baseExpression = new GrammarDefinition("BaseExpression",
                rule: ToElement(BASE),
                createNode: node => new BaseReferenceExpression()
                {
                    BaseKeywordToken = (AstToken) node.Children[0].Result,
                });

            var typeofExpression = new GrammarDefinition("TypeOfExpression",
                rule: ToElement(TYPEOF) + ToElement(OPEN_PARENS) + typeReference
                      + ToElement(CLOSE_PARENS),
                createNode: node => new GetTypeExpression()
                {
                    GetTypeKeywordToken = (AstToken) node.Children[0].Result,
                    LeftParenthese = (AstToken) node.Children[1].Result,
                    TargetType = (TypeReference) node.Children[2].Result,
                    RightParenthese = (AstToken) node.Children[3].Result,
                });

            var defaultExpression = new GrammarDefinition("DefaultExpression",
                rule: ToElement(DEFAULT)
                      + ToElement(OPEN_PARENS)
                      + typeReference
                      + ToElement(CLOSE_PARENS),
                createNode: node => new DefaultExpression()
                {
                    KeywordToken = (AstToken) node.Children[0].Result,
                    LeftParenthese = (AstToken) node.Children[1].Result,
                    TargetType = (TypeReference) node.Children[2].Result,
                    RightParenthese = (AstToken) node.Children[3].Result,
                });

            var sizeofExpression = new GrammarDefinition("SizeOfExpression",
                rule: ToElement(SIZEOF) + ToElement(OPEN_PARENS) + typeReference
                      + ToElement(CLOSE_PARENS),
                createNode: node => new SizeOfExpression()
                {
                    SizeofKeyword = (AstToken) node.Children[0].Result,
                    LeftParenthese = (AstToken) node.Children[1].Result,
                    TargetType = (TypeReference) node.Children[2].Result,
                    RightParenthese = (AstToken) node.Children[3].Result,
                });

            var checkedExpression = new GrammarDefinition("CheckedExpression",
                rule:
                    ToElement(CHECKED) + ToElement(OPEN_PARENS) + expression +
                    ToElement(CLOSE_PARENS),
                createNode: node => new CheckedExpression()
                {
                    CheckedKeyword = (AstToken) node.Children[0].Result,
                    LeftParenthese = (AstToken) node.Children[1].Result,
                    TargetExpression = (Expression) node.Children[2].Result,
                    RightParenthese = (AstToken) node.Children[3].Result,
                });

            var uncheckedExpression = new GrammarDefinition("UncheckedExpression",
                rule:
                    ToElement(UNCHECKED) + ToElement(OPEN_PARENS) + expression +
                    ToElement(CLOSE_PARENS),
                createNode: node => new UncheckedExpression()
                {
                    UncheckedKeyword = (AstToken) node.Children[0].Result,
                    LeftParenthese = (AstToken) node.Children[1].Result,
                    TargetExpression = (Expression) node.Children[2].Result,
                    RightParenthese = (AstToken) node.Children[3].Result,
                });

            var stackAllocExpression = new GrammarDefinition("StackAllocExpression",
                rule:
                    ToElement(STACKALLOC)
                    + typeReference
                    + ToElement(OPEN_BRACKET_EXPR)
                    + expression
                    + ToElement(CLOSE_BRACKET),
                createNode: node => new StackAllocExpression()
                {
                    StackAllocKeyword = (AstToken) node.Children[0].Result,
                    Type = (TypeReference) node.Children[1].Result,
                    LeftBracket = (AstToken) node.Children[2].Result,
                    Counter = (Expression) node.Children[3].Result,
                    RightBracket = (AstToken) node.Children[4].Result,
                });

            var explicitAnonymousMethodParameter = new GrammarDefinition("ExplicitAnonymousMethodParameter",
                rule: typeReference + ToElement(IDENTIFIER),
                createNode: node => new ParameterDeclaration
                {
                    ParameterType = (TypeReference)node.Children[0].Result,
                    Declarator = new VariableDeclarator(ToIdentifier(node.Children[1].Result))
                });

            var explicitAnonymousMethodParameterList = new GrammarDefinition("ExplicitAnonymousMethodParameterList");
            explicitAnonymousMethodParameterList.Rule = explicitAnonymousMethodParameter
                                                        | explicitAnonymousMethodParameterList
                                                        + ToElement(COMMA)
                                                        + explicitAnonymousMethodParameter;

            var explicitAnonymousMethodParameterListOptional = new GrammarDefinition("ExplicitAnonymousMethodParameterListOptional",
                rule: null | explicitAnonymousMethodParameterList);

            var explicitAnonymousMethodSignature = new GrammarDefinition("ExplicitAnonymousMethodSignature",
                rule: ToElement(OPEN_PARENS) + explicitAnonymousMethodParameterListOptional + ToElement(CLOSE_PARENS));

            var explicitAnonymousMethodSignatureOptional =
                new GrammarDefinition("ExplicitAnonymousMethodSignatureOptional",
                    rule: null | explicitAnonymousMethodSignature);

            var anonymousMethodExpression = new GrammarDefinition("AnonymousMethodExpression",
                rule: ToElement(DELEGATE) + explicitAnonymousMethodSignatureOptional + blockStatement,
                createNode: node =>
                {
                    var result = new AnonymousMethodExpression();
                    result.DelegateKeyword = (AstToken) node.Children[0].Result;

                    if (node.Children[1].HasChildren)
                    {
                        var signature = node.Children[1].Children[0];
                        result.LeftParenthese = (AstToken) signature.Children[0].Result;

                        if (signature.Children[1].HasChildren)
                        {
                            foreach (var child in signature.Children[1].Children[0].GetAllListAstNodes())
                            {
                                if (child is AstToken)
                                    result.AddChild(AstNodeTitles.ElementSeparator, child);
                                else
                                    result.Parameters.Add((ParameterDeclaration) child);
                            }
                        }

                        result.RightParenthese = (AstToken)signature.Children[2].Result;
                    }

                    result.Body = (BlockStatement) node.Children[2].Result;
                    return result;
                });


            var implicitAnonymousMethodParameter = new GrammarDefinition("ImplicitAnonymousMethodParameter",
                rule: ToElement(IDENTIFIER),
                createNode: node => new ParameterDeclaration
                {
                    Declarator = new VariableDeclarator(ToIdentifier(node.Children[0].Result))
                });

            var implicitAnonymousMethodParameterList = new GrammarDefinition("ImplicitAnonymousMethodParameterList");
            implicitAnonymousMethodParameterList.Rule = implicitAnonymousMethodParameter
                                                        | implicitAnonymousMethodParameterList
                                                        + ToElement(COMMA)
                                                        + implicitAnonymousMethodParameter;

            var implicitAnonymousMethodParameterListOptional = new GrammarDefinition("ImplicitAnonymousMethodParameterListOptional",
                rule: null | implicitAnonymousMethodParameterList);

            var implicitAnonymousMethodSignature = new GrammarDefinition("implicitAnonymousMethodSignature",
                rule: implicitAnonymousMethodParameter | ToElement(OPEN_PARENS_LAMBDA) + implicitAnonymousMethodParameterList + ToElement(CLOSE_PARENS));

            var anonymousMethodSignature = new GrammarDefinition("AnonymousMethodSignature",
                rule: implicitAnonymousMethodSignature);

            var anonymousFunctionBody = new GrammarDefinition("AnonymousFunctionBody",
                rule: expression | blockStatement);

            var lambdaExpression = new GrammarDefinition("LambdaExpression",
                rule: anonymousMethodSignature + ToElement(ARROW) + anonymousFunctionBody,
                createNode: node =>
                {
                    var result = new LambdaExpression();
                    result.Arrow = (AstToken)node.Children[1].Result;
                    result.Body = node.Children[2].Result;
                    return result;

                });

            primaryExpression.Rule =
                typeNameExpression
                | primitiveExpression
                | parenthesizedExpression
                | invocationExpression
                | indexerExpression
                | thisExpression
                | baseExpression
                | createObjectExpression
                | createArrayExpression
                | typeofExpression
                | defaultExpression
                | sizeofExpression
                | checkedExpression
                | uncheckedExpression
                | stackAllocExpression
                | anonymousMethodExpression
                ;

            var preFixUnaryOperator = new GrammarDefinition("PreFixUnaryOperator",
                rule: ToElement(PLUS)
                      | ToElement(MINUS)
                      | ToElement(STAR)
                      | ToElement(BANG)
                      | ToElement(OP_INC)
                      | ToElement(OP_DEC)
                      | ToElement(BITWISE_AND)
                      | ToElement(TILDE)
                      | ToElement(AWAIT));
            var postFixUnaryOperator = new GrammarDefinition("PostFixUnaryOperator",
                rule: ToElement(OP_INC)
                      | ToElement(OP_DEC));


            var castExpression = new GrammarDefinition("CastExpression");

            var unaryOperatorExpression = new GrammarDefinition("UnaryOperatorExpression",
                rule: primaryExpression
                      | castExpression
                      | (preFixUnaryOperator + primaryExpression)
                      | (primaryExpression + postFixUnaryOperator),
                createNode: node =>
                {
                    if (node.Children.Count == 1)
                        return node.Children[0].Result;

                    var result = new UnaryOperatorExpression();
                    var isPrefix = node.Children[0].GrammarElement == preFixUnaryOperator;
                    if (isPrefix)
                    {
                        var operatorToken = ((AstToken) node.Children[0].Children[0].Result);
                        result.Operator = CSharpLanguage.UnaryOperatorFromString(operatorToken.Value);
                        result.OperatorToken = operatorToken;
                    }

                    result.Expression = (Expression) node.Children[isPrefix ? 1 : 0].Result;
                    if (!isPrefix)
                    {
                        var operatorToken = (AstToken) node.Children[1].Children[0].Result;
                        result.Operator = CSharpLanguage.UnaryOperatorFromString(operatorToken.Value, false);
                        result.OperatorToken = operatorToken;
                    }
                    return result;
                });

            castExpression.Rule = ToElement(OPEN_PARENS)
                                  + typeNameExpression
                                  + ToElement(CLOSE_PARENS)
                                  + unaryOperatorExpression;
            castExpression.ComputeResult = node => new ExplicitCastExpression
            {
                LeftParenthese = (AstToken) node.Children[0].Result,
                TargetType = ToTypeReference((IConvertibleToType) node.Children[1].Result),
                RightParenthese = (AstToken) node.Children[2].Result,
                TargetExpression = (Expression) node.Children[3].Result
            };

            var multiplicativeOperator = new GrammarDefinition("MultiplicativeOperator",
                rule: ToElement(STAR)
                      | ToElement(DIV)
                      | ToElement(PERCENT));

            var multiplicativeExpression = new GrammarDefinition("MultiplicativeExpression");
            multiplicativeExpression.Rule = unaryOperatorExpression
                                            | multiplicativeExpression
                                            + multiplicativeOperator
                                            + unaryOperatorExpression;
            multiplicativeExpression.ComputeResult = createBinaryOperatorExpression;

            var additiveOperator = new GrammarDefinition("AdditiveOperator",
                rule: ToElement(PLUS)
                      | ToElement(MINUS));
            var additiveExpression = new GrammarDefinition("AdditiveExpression");
            additiveExpression.Rule = multiplicativeExpression
                                      | additiveExpression
                                      + additiveOperator
                                      + multiplicativeExpression;
            additiveExpression.ComputeResult = createBinaryOperatorExpression;

            var shiftOperator = new GrammarDefinition("ShiftOperator",
                rule: ToElement(OP_SHIFT_LEFT)
                      | ToElement(OP_SHIFT_RIGHT));
            var shiftExpression = new GrammarDefinition("ShiftExpression");
            shiftExpression.Rule = additiveExpression
                                   | shiftExpression
                                   + shiftOperator
                                   + additiveExpression;
            shiftExpression.ComputeResult = createBinaryOperatorExpression;

            var relationalOperator = new GrammarDefinition("RelationalOperator",
                rule: ToElement(OP_GT)
                      | ToElement(OP_GE)
                      | ToElement(OP_LT)
                      | ToElement(OP_LE)
                      | ToElement(IS)
                      | ToElement(AS));
            var relationalExpression = new GrammarDefinition("RelationalExpression");
            relationalExpression.Rule = shiftExpression
                                        | relationalExpression
                                        + relationalOperator
                                        + shiftExpression;
            relationalExpression.ComputeResult = node =>
            {
                if (node.Children.Count == 1)
                    return node.Children[0].Result;
                var operatorToken = (CSharpAstToken) node.Children[1].Children[0].Result;
                switch (operatorToken.Code)
                {
                    case IS:
                        return new TypeCheckExpression()
                        {
                            TargetExpression = (Expression) node.Children[0].Result,
                            IsKeyword = operatorToken,
                            TargetType = ToTypeReference((IConvertibleToType) node.Children[2].Result)
                        };
                    case AS:
                        return new SafeCastExpression()
                        {
                            TargetExpression = (Expression) node.Children[0].Result,
                            CastKeyword = operatorToken,
                            TargetType = ToTypeReference((IConvertibleToType) node.Children[2].Result)
                        };
                    default:
                        return createBinaryOperatorExpression(node);
                }
            };

            var equalityOperator = new GrammarDefinition("equalityOperator",
                rule: ToElement(OP_EQUALS)
                      | ToElement(OP_NOTEQUALS));
            var equalityExpression = new GrammarDefinition("EqualityExpression");
            equalityExpression.Rule = relationalExpression
                                      | equalityExpression
                                      + equalityOperator
                                      + relationalExpression;
            equalityExpression.ComputeResult = createBinaryOperatorExpression;

            var logicalAndExpression = new GrammarDefinition("LogicalAndExpression");
            logicalAndExpression.Rule = equalityExpression
                                      | logicalAndExpression
                                      + ToElement(BITWISE_AND)
                                      + equalityExpression;
            logicalAndExpression.ComputeResult = createBinaryOperatorExpression;

            var logicalXorExpression = new GrammarDefinition("LogicalOrExpression");
            logicalXorExpression.Rule = logicalAndExpression
                                      | logicalXorExpression
                                      + ToElement(CARRET)
                                      + logicalAndExpression;
            logicalXorExpression.ComputeResult = createBinaryOperatorExpression;

            var logicalOrExpression = new GrammarDefinition("LogicalOrExpression");
            logicalOrExpression.Rule = logicalXorExpression
                                      | logicalOrExpression
                                      + ToElement(BITWISE_OR)
                                      + logicalXorExpression;
            logicalOrExpression.ComputeResult = createBinaryOperatorExpression;

            var conditionalAndExpression = new GrammarDefinition("ConditionalAndExpression");
            conditionalAndExpression.Rule = logicalOrExpression
                                      | conditionalAndExpression
                                      + ToElement(OP_AND)
                                      + logicalOrExpression;
            conditionalAndExpression.ComputeResult = createBinaryOperatorExpression;

            var conditionalOrExpression = new GrammarDefinition("ConditionalOrExpression");
            conditionalOrExpression.Rule = conditionalAndExpression
                                      | conditionalOrExpression
                                      + ToElement(OP_OR)
                                      + conditionalAndExpression;
            conditionalOrExpression.ComputeResult = createBinaryOperatorExpression;

            var nullCoalescingExpression = new GrammarDefinition("NullCoalescingExpression");
            nullCoalescingExpression.Rule = conditionalOrExpression
                                      | nullCoalescingExpression
                                      + ToElement(OP_COALESCING)
                                      + conditionalOrExpression;
            nullCoalescingExpression.ComputeResult = createBinaryOperatorExpression;

            var conditionalExpression = new GrammarDefinition("ConditionalExpression",
                rule: nullCoalescingExpression
                      | nullCoalescingExpression
                      + ToElement(INTERR)
                      + expression + ToElement(COLON) + expression,
                createNode: node => node.Children.Count == 1
                    ? node.Children[0].Result
                    : new ConditionalExpression
                    {
                        Condition = (Expression) node.Children[0].Result,
                        OperatorToken = (AstToken) node.Children[1].Result,
                        TrueExpression = (Expression) node.Children[2].Result,
                        ColonToken = (AstToken) node.Children[3].Result,
                        FalseExpression = (Expression) node.Children[4].Result
                    });

            var assignmentOperator = new GrammarDefinition("AssignmentOperator",
                rule: ToElement(EQUALS)
                      | ToElement(OP_ADD_ASSIGN)
                      | ToElement(OP_SUB_ASSIGN)
                      | ToElement(OP_MULT_ASSIGN)
                      | ToElement(OP_DIV_ASSIGN)
                      | ToElement(OP_AND_ASSIGN)
                      | ToElement(OP_OR_ASSIGN)
                      | ToElement(OP_XOR_ASSIGN)
                      | ToElement(OP_SHIFT_LEFT_ASSIGN)
                      | ToElement(OP_SHIFT_RIGHT_ASSIGN));
            var assignmentExpression = new GrammarDefinition("AssignmentExpression",
                rule: unaryOperatorExpression
                      + assignmentOperator
                      + expression,
                createNode: node => new AssignmentExpression
                {
                    Target = (Expression) node.Children[0].Result,
                    Operator = CSharpLanguage.AssignmentOperatorFromString(((AstToken) node.Children[1].Children[0].Result).Value),
                    OperatorToken = (AstToken) node.Children[1].Children[0].Result,
                    Value = (Expression) node.Children[2].Result,
                });

            var fromClause = new GrammarDefinition("FromClause",
                rule: ToElement(FROM) + identifierInsideBody + ToElement(IN) + expression,
                createNode: node => new LinqFromClause
                {
                    FromKeyword = (AstToken) node.Children[0].Result,
                    VariableName = (Identifier) node.Children[1].Result,
                    InKeyword = (AstToken) node.Children[2].Result,
                    DataSource = (Expression) node.Children[3].Result
                });

            var letClause = new GrammarDefinition("LetClause",
                rule: ToElement(LET) + variableDeclarator,
                createNode: node => new LinqLetClause()
                {
                    LetKeyword = (AstToken) node.Children[0].Result,
                    Variable = (VariableDeclarator) node.Children[1].Result
                });

            var whereClause = new GrammarDefinition("WhereClause",
                rule: ToElement(WHERE) + expression,
                createNode: node => new LinqWhereClause()
                {
                    WhereKeyword = (AstToken) node.Children[0].Result,
                    Condition = (Expression) node.Children[1].Result
                });

            var orderingDirection = new GrammarDefinition("OrderingDirection",
                rule: null | ToElement(ASCENDING) | ToElement(DESCENDING));

            var ordering = new GrammarDefinition("Ordering",
                rule: expression + orderingDirection,
                createNode: node =>
                {
                    var result = new LinqOrdering();
                    result.Expression = (Expression) node.Children[0].Result;

                    if (node.Children[1].HasChildren)
                    {
                        var directionNode = node.Children[1].Children[0];
                        result.DirectionKeyword = (AstToken) directionNode.Result;
                        result.Direction = directionNode.Result != null
                            ? CSharpLanguage.OrderningDirectionFromString(result.DirectionKeyword.Value)
                            : LinqOrderingDirection.None;
                    }

                    return result;
                });

            var orderings = new GrammarDefinition("Orderings");
            orderings.Rule = ordering | orderings + ToElement(COMMA) + ordering;

            var orderByClause = new GrammarDefinition("OrderByClause",
                rule: ToElement(ORDERBY) + orderings,
                createNode: node =>
                {
                    var result = new LinqOrderByClause();
                    result.OrderByKeyword = (AstToken) node.Children[0].Result;
                    foreach (var subNode in node.Children[1].GetAllListAstNodes())
                    {
                        if (subNode is AstToken)
                            result.AddChild(AstNodeTitles.ElementSeparator, subNode);
                        else
                            result.Ordernings.Add((LinqOrdering) subNode);
                    }
                    return result;
                });

            var groupByClause = new GrammarDefinition("GroupByClause",
                rule: ToElement(GROUP) + expression + ToElement(BY) + expression,
                createNode: node => new LinqGroupByClause()
                {
                    GroupKeyword = (AstToken) node.Children[0].Result,
                    Expression = (Expression) node.Children[1].Result,
                    ByKeyword = (AstToken) node.Children[2].Result,
                    KeyExpression = (Expression) node.Children[3].Result
                });

            var selectClause = new GrammarDefinition("SelectClause",
                rule: ToElement(SELECT) + expression,
                createNode: node => new LinqSelectClause()
                {
                    SelectKeyword = (AstToken) node.Children[0].Result,
                    Target = (Expression) node.Children[1].Result
                });

            var queryBodyClause = new GrammarDefinition("QueryBodyClause",
                rule:
                fromClause
                | letClause
                | groupByClause
                | whereClause
                | orderByClause
                 );

            var queryBodyClauses = new GrammarDefinition("QueryBodyClauses");
            queryBodyClauses.Rule = queryBodyClause | queryBodyClauses + queryBodyClause;

            var queryBodyClausesOptional = new GrammarDefinition("QueryBodyClausesOptional",
                rule: null | queryBodyClauses);

            var linqExpression = new GrammarDefinition("LinqExpression",
                rule: fromClause + queryBodyClausesOptional + selectClause,
                createNode: node =>
                {
                    var result = new LinqExpression();
                    result.Clauses.Add((LinqClause) node.Children[0].Result);

                    if (node.Children[1].HasChildren)
                    {
                        result.Clauses.AddRange(node.Children[1].Children[0].GetAllListAstNodes().Cast<LinqClause>());
                    }

                    result.Clauses.Add((LinqClause) node.Children[2].Result);
                    return result;
                });

            expression.Rule = conditionalExpression
                              | linqExpression
                              | lambdaExpression
                              | assignmentExpression;

            #endregion

            #region Statements
            var statement = new GrammarDefinition("Statement");
            var embeddedStatement = new GrammarDefinition("EmbeddedStatement");

            var emptyStatement = new GrammarDefinition("EmptyStatement",
                rule: ToElement(SEMICOLON),
                createNode: node =>
                {
                    var result = new EmptyStatement();
                    result.AddChild(AstNodeTitles.Semicolon, node.Children[0].Result);
                    return result;
                });

            var labelStatement = new GrammarDefinition("LabelStatement",
                rule: identifierInsideBody + ToElement(COLON),
                createNode: node => new LabelStatement((Identifier) node.Children[0].Result)
                {
                    Colon = (AstToken) node.Children[1].Result
                });

            var expressionStatement = new GrammarDefinition("ExpressionStatement",
                rule: expression + ToElement(SEMICOLON)
                      | Error + ToElement(SEMICOLON)
                      | Error + ToElement(CLOSE_BRACE)
                      | expression + ToElement(CLOSE_BRACE), // Common mistake in C# is to forget the semicolon at the end of a statement.
                createNode: node =>
                {
                    var result = new ExpressionStatement(node.Children[0].Result as Expression);

                    var endingToken = (AstToken) node.Children[1].Result;
                    if (endingToken.GetTokenCode() == (int) SEMICOLON)
                    {
                        result.AddChild(AstNodeTitles.Semicolon, node.Children[1].Result);
                    }
                    else
                    {
                        node.Context.SyntaxErrors.Add(new SyntaxError(
                            node.Children[1].Range.End, 
                            "';' expected.", 
                            MessageSeverity.Error));
                        
                        node.Context.Lexer.PutBack((AstToken) endingToken);
                    }

                    return result;
                });

            blockStatement.Rule = ToElement(OPEN_BRACE)
                                  + statementListOptional
                                  + ToElement(CLOSE_BRACE);
            blockStatement.ComputeResult = node =>
            {
                var result = new BlockStatement();
                result.StartScope = node.Children[0].Result;
                if (node.Children[1].HasChildren)
                {
                    result.Statements.AddRange(node.Children[1].Children[0].GetAllListAstNodes<Statement>());
                }
                result.EndScope = node.Children[2].Result;
                return result;
            };

            var variableDeclarationStatement = new GrammarDefinition("VariableDeclarationStatement",
                rule: variableDeclaration
                      + ToElement(SEMICOLON),
                createNode: node =>
                {
                    var result = node.Children[0].Result;
                    result.AddChild(AstNodeTitles.Semicolon, node.Children[1].Result);
                    return result;
                });

            var ifElseStatement = new GrammarDefinition("IfElseStatement",
                rule: ToElement(IF) + parenthesizedExpression + embeddedStatement
                | ToElement(IF) + parenthesizedExpression + embeddedStatement + ToElement(ELSE) + embeddedStatement
                ,
                createNode: node =>
                {
                    var result = new IfElseStatement();
                    result.IfKeyword = (AstToken) node.Children[0].Result;

                    var parenthesized = (ParenthesizedExpression) node.Children[1].Result;
                    result.LeftParenthese = (AstToken) parenthesized.LeftParenthese.Remove();
                    result.Condition = (Expression) parenthesized.Expression?.Remove();
                    result.RightParenthese = (AstToken) parenthesized.RightParenthese.Remove();

                    result.TrueBlock = (Statement) node.Children[2].Result;

                    if (node.Children.Count > 3)
                    {
                        result.ElseKeyword = (AstToken) node.Children[3].Result;
                        result.FalseBlock = (Statement) node.Children[4].Result;
                        CheckForPossibleMistakenEmptyStatement(node.Children[4]);
                    }
                    else
                    {
                        CheckForPossibleMistakenEmptyStatement(node.Children[2]);
                    }

                    return result;
                });

            var switchLabel = new GrammarDefinition("SwitchLabel",
                rule: ToElement(CASE) + expression + ToElement(COLON)
                      | ToElement(DEFAULT_COLON) + ToElement(COLON),
                createNode: node =>
                {
                    var result = new SwitchCaseLabel();
                    result.CaseKeyword = (AstToken) node.Children[0].Result;
                    if (node.Children.Count > 2)
                        result.Condition = (Expression) node.Children[1].Result;
                    result.Colon = (AstToken) node.Children[node.Children.Count - 1].Result;
                    return result;
                });

            var switchLabels = new GrammarDefinition("SwitchLabels");
            switchLabels.Rule = switchLabel | switchLabels + switchLabel;

            var switchSection = new GrammarDefinition("SwitchSection",
                rule: switchLabels + statementList,
                createNode: node =>
                {
                    var result = new SwitchSection();
                    result.Labels.AddRange(node.Children[0].GetAllListAstNodes<SwitchCaseLabel>());

                    result.Statements.AddRange(node.Children[1].GetAllListAstNodes<Statement>());

                    return result;
                });

            var switchSections = new GrammarDefinition("SwitchSections");
            switchSections.Rule = switchSection
                                  | switchSections + switchSection;

            var switchBlock = new GrammarDefinition("SwitchBlock",
                rule: ToElement(OPEN_BRACE)
                      + switchSections
                      + ToElement(CLOSE_BRACE));

            var switchStatement = new GrammarDefinition("SwitchStatement",
                rule: ToElement(SWITCH)
                      + ToElement(OPEN_PARENS)
                      + expression
                      + ToElement(CLOSE_PARENS)
                      + switchBlock,
                createNode: node =>
                {
                    var result = new SwitchStatement();
                    result.SwitchKeyword = (AstToken) node.Children[0].Result;
                    result.LeftParenthese = (AstToken) node.Children[1].Result;
                    result.Condition = (Expression) node.Children[2].Result;
                    result.RightParenthese = (AstToken) node.Children[3].Result;
                    var switchBlockNode = node.Children[4];
                    result.StartScope = switchBlockNode.Children[0].Result;
                    result.Sections.AddRange(switchBlockNode.Children[1].GetAllListAstNodes<SwitchSection>());
                    result.EndScope = switchBlockNode.Children[2].Result;
                    return result;
                });

            var selectionStatement = new GrammarDefinition("SelectionStatement",
                rule: ifElseStatement
                      | switchStatement);

            var whileLoopStatement = new GrammarDefinition("WhileLoopStatement",
                rule: ToElement(WHILE)
                      + parenthesizedExpression
                      + embeddedStatement,
                createNode: node =>
                {
                    var bodyNode = node.Children[2];
                    CheckForPossibleMistakenEmptyStatement(bodyNode);

                    var conditionExpr = (ParenthesizedExpression) node.Children[1].Result;
                    return new WhileLoopStatement
                    {
                        WhileKeyword = (AstToken) node.Children[0].Result,
                        LeftParenthese = (AstToken) conditionExpr.LeftParenthese.Remove(),
                        Condition = (Expression) conditionExpr.Expression.Remove(),
                        RightParenthese = (AstToken) conditionExpr.RightParenthese.Remove(),
                        Body = (Statement) bodyNode.Result
                    };
                });

            var doLoopStatement = new GrammarDefinition("DoLoopStatement",
                rule: ToElement(DO)
                      + embeddedStatement
                      + ToElement(WHILE)
                      + parenthesizedExpression
                      + ToElement(SEMICOLON),
                createNode: node =>
                {
                    var conditionExpr = (ParenthesizedExpression) node.Children[3].Result;
                    return new DoLoopStatement
                    {
                        DoKeyword = (AstToken) node.Children[0].Result,
                        Body = (Statement) node.Children[1].Result,
                        WhileKeyword = (AstToken) node.Children[2].Result,
                        LeftParenthese = (AstToken) conditionExpr.LeftParenthese.Remove(),
                        Condition = (Expression) conditionExpr.Expression.Remove(),
                        RightParenthese = (AstToken) conditionExpr.RightParenthese.Remove(),
                        Semicolon = (AstToken) node.Children[4].Result
                    };
                });

            var forLoopInitializer = new GrammarDefinition("ForLoopInitializer",
                rule: variableDeclaration
                     | null
                     // TODO: statement-expression-list
                     );

            var forLoopCondition = new GrammarDefinition("ForLoopCondition",
                rule: expression
                | null);

            var forLoopStatement = new GrammarDefinition("ForLoopStatement",
                rule: ToElement(FOR)
                + ToElement(OPEN_PARENS)
                + forLoopInitializer
                + ToElement(SEMICOLON)
                + expressionOptional
                + ToElement(SEMICOLON)
                + expressionOptional // TODO: statement-expression-list
                + ToElement(CLOSE_PARENS)
                + embeddedStatement,
                createNode: node =>
                {
                    var result = new ForLoopStatement();
                    result.ForKeyword = (AstToken) node.Children[0].Result;
                    result.LeftParenthese = (AstToken) node.Children[1].Result;

                    if (node.Children[2].HasChildren)
                    {
                        var declaration = node.Children[2].Children[0].Result as VariableDeclarationStatement;
                        if (declaration != null)
                        {
                            result.Initializers.Add(declaration);
                        }
                        else
                        {
                            result.Initializers.AddRange(node.Children[2].GetAllListAstNodes<Expression>()
                                .Select(x => new ExpressionStatement(x)));
                        }
                    }

                    result.AddChild(AstNodeTitles.Semicolon, node.Children[3].Result);

                    if (node.Children[4].HasChildren)
                        result.Condition = (Expression) node.Children[4].Result;

                    result.AddChild(AstNodeTitles.Semicolon, node.Children[5].Result);

                    if (node.Children[6].HasChildren)
                    {
                        result.Iterators.AddRange(node.Children[6].Children[0].GetAllListAstNodes<Expression>()
                            .Select(x => new ExpressionStatement(x)));
                    }

                    result.RightParenthese = (AstToken) node.Children[7].Result;

                    var bodyNode = node.Children[8];
                    CheckForPossibleMistakenEmptyStatement(bodyNode);
                    result.Body = (Statement) bodyNode.Result;

                    return result;
                });

            var foreachLoopStatement = new GrammarDefinition("ForEachLoopStatement",
                rule: ToElement(FOREACH)
                      + ToElement(OPEN_PARENS)
                      + typeReference
                      + identifierInsideBody
                      + ToElement(IN)
                      + expression
                      + ToElement(CLOSE_PARENS)
                      + embeddedStatement,
                createNode: node =>
                {
                    var bodyNode = node.Children[7];
                    CheckForPossibleMistakenEmptyStatement(bodyNode);

                    return new ForeachLoopStatement
                    {
                        ForeachKeyword = (AstToken) node.Children[0].Result,
                        LeftParenthese = (AstToken) node.Children[1].Result,
                        Type = (TypeReference) node.Children[2].Result,
                        Identifier = (Identifier) node.Children[3].Result,
                        InKeyword = (AstToken) node.Children[4].Result,
                        Target = (Expression) node.Children[5].Result,
                        RightParenthese = (AstToken) node.Children[6].Result,
                        Body = (Statement) bodyNode.Result
                    };
                });

            var loopStatement = new GrammarDefinition("LoopStatement",
                rule: whileLoopStatement
                      | doLoopStatement
                      | forLoopStatement
                      | foreachLoopStatement);

            var lockStatement = new GrammarDefinition("LockStatement",
                rule: ToElement(LOCK)
                      + ToElement(OPEN_PARENS)
                      + expression
                      + ToElement(CLOSE_PARENS)
                      + statement,
                createNode: node =>
                {
                    var bodyNode = node.Children[4];
                    CheckForPossibleMistakenEmptyStatement(bodyNode);

                    return new LockStatement
                    {
                        LockKeyword = (AstToken) node.Children[0].Result,
                        LeftParenthese = (AstToken) node.Children[1].Result,
                        LockObject = (Expression) node.Children[2].Result,
                        RightParenthese = (AstToken) node.Children[3].Result,
                        Body = (Statement) bodyNode.Result
                    };
                });

            var resourceAcquisition = new GrammarDefinition("ResourceAcquisition",
                rule: variableDeclaration | expression);

            var usingStatement = new GrammarDefinition("UsingStatement",
                rule: ToElement(USING)
                      + ToElement(OPEN_PARENS)
                      + resourceAcquisition
                      + ToElement(CLOSE_PARENS)
                      + statement,
                createNode: node =>
                {
                    var bodyNode = node.Children[4];
                    CheckForPossibleMistakenEmptyStatement(bodyNode);

                    return new UsingStatement()
                    {
                        UsingKeyword = (AstToken) node.Children[0].Result,
                        LeftParenthese = (AstToken) node.Children[1].Result,
                        DisposableObject = node.Children[2].Result,
                        RightParenthese = (AstToken) node.Children[3].Result,
                        Body = (Statement) bodyNode.Result
                    };
                });

            var breakStatement = new GrammarDefinition("BreakStatement",
                rule: ToElement(BREAK)
                      + ToElement(SEMICOLON),
                createNode: node => new BreakStatement()
                {
                    Keyword = (AstToken) node.Children[0].Result,
                    Semicolon = (AstToken) node.Children[1].Result
                });

            var continueStatement = new GrammarDefinition("ContinueStatement",
                rule: ToElement(CONTINUE)
                      + ToElement(SEMICOLON),
                createNode: node => new BreakStatement()
                {
                    Keyword = (AstToken) node.Children[0].Result,
                    Semicolon = (AstToken) node.Children[1].Result
                });

            var returnStatement = new GrammarDefinition("ReturnStatement",
                rule: ToElement(RETURN)
                      + expressionOptional
                      + ToElement(SEMICOLON),
                createNode: node =>
                {
                    var result = new ReturnStatement();
                    result.ReturnKeyword = (AstToken) node.Children[0].Result;
                    if (node.Children[1].HasChildren)
                        result.Value = (Expression) node.Children[1].Result;
                    result.AddChild(AstNodeTitles.Semicolon, node.Children[2].Result);
                    return result;
                });

            var throwStatement = new GrammarDefinition("ThrowStatement",
                rule: ToElement(THROW)
                      + expressionOptional
                      + ToElement(SEMICOLON),
                createNode: node =>
                {
                    var result = new ThrowStatement();
                    result.ThrowKeyword = (AstToken) node.Children[0].Result;
                    if (node.Children[1].HasChildren)
                        result.Expression = (Expression) node.Children[1].Result;
                    result.AddChild(AstNodeTitles.Semicolon, node.Children[2].Result);
                    return result;
                });

            var gotoStatement = new GrammarDefinition("GotoStatement",
                rule: ToElement(GOTO)
                      + identifierInsideBody
                      + ToElement(SEMICOLON),
                // TODO: goto case and goto default statements.
                createNode: node =>
                {
                    var result = new GotoStatement();
                    result.GotoKeyword = (AstToken) node.Children[0].Result;
                    result.LabelIdentifier = (Identifier) node.Children[1].Result;
                    result.AddChild(AstNodeTitles.Semicolon, node.Children[2].Result);
                    return result;
                });

            var jumpStatement = new GrammarDefinition("JumpStatement",
                rule: breakStatement
                      | continueStatement
                      | gotoStatement
                      | returnStatement
                      | throwStatement);

            var yieldStatement = new GrammarDefinition("YieldStatement",
                rule: ToElement(YIELD)
                      + ToElement(RETURN)
                      + expression
                      + ToElement(SEMICOLON),
                createNode: node => new YieldStatement()
                {
                    YieldKeyword = (AstToken) node.Children[0].Result,
                    ReturnKeyword = (AstToken) node.Children[1].Result,
                    Value = (Expression) node.Children[2].Result
                });

            var yieldBreakStatement = new GrammarDefinition("YieldBreakStatement",
                rule: ToElement(YIELD)
                      + ToElement(BREAK)
                      + ToElement(SEMICOLON),
                createNode: node => new YieldBreakStatement()
                {
                    Keyword = (AstToken) node.Children[0].Result,
                    BreakKeyword = (AstToken) node.Children[1].Result
                });

            var specificCatchClause = new GrammarDefinition("SpecificCatchClause",
                rule: ToElement(CATCH) + ToElement(OPEN_PARENS)
                    + namespaceOrTypeExpression + identifierInsideBodyOptional + ToElement(CLOSE_PARENS)
                    + blockStatement,
                createNode: node =>
                {
                    var result = new CatchClause();
                    result.CatchKeyword = (AstToken) node.Children[0].Result;
                    result.LeftParenthese = (AstToken) node.Children[1].Result;
                    result.ExceptionType = (TypeReference) node.Children[2].Result;

                    if (node.Children[3].HasChildren)
                        result.ExceptionIdentifier = (Identifier) node.Children[3].Result;

                    result.RightParenthese = (AstToken) node.Children[4].Result;
                    result.Body = (BlockStatement) node.Children[5].Result;
                    return result;
                });

            var generalCatchClause = new GrammarDefinition("GeneralCatchClause",
                rule: ToElement(CATCH) + blockStatement,
                createNode: node => new CatchClause
                {
                    CatchKeyword = (AstToken) node.Children[0].Result,
                    Body = (BlockStatement) node.Children[1].Result
                });

            var catchClause = new GrammarDefinition("CatchClause",
                rule: specificCatchClause | generalCatchClause);

            var catchClauses = new GrammarDefinition("CatchClauses");
            catchClauses.Rule = catchClause | catchClauses + catchClause;

            var finallyClause = new GrammarDefinition("FinallyClause",
                rule: ToElement(FINALLY) + blockStatement);

            var tryCatchStatement = new GrammarDefinition("TryCatchStatement",
                rule: ToElement(TRY) + blockStatement + catchClauses
                      | ToElement(TRY) + blockStatement + finallyClause
                      | ToElement(TRY) + blockStatement + catchClauses + finallyClause,
                createNode: node =>
                {
                    var result = new TryCatchStatement();
                    result.TryKeyword = (AstToken) node.Children[0].Result;
                    result.TryBlock = (BlockStatement) node.Children[1].Result;

                    ParserNode finallyClauseNode = null;
                    if (node.Children[2].GrammarElement == finallyClause)
                    {
                        finallyClauseNode = node.Children[2];
                    }
                    else
                    {
                        result.CatchClauses.AddRange(node.Children[2].GetAllListAstNodes<CatchClause>());
                    }

                    if (node.Children.Count == 4)
                        finallyClauseNode = node.Children[3];

                    if (finallyClauseNode != null)
                    {
                        result.FinallyKeyword = (AstToken) finallyClauseNode.Children[0].Result;
                        result.FinallyBlock = (BlockStatement) finallyClauseNode.Children[1].Result;
                    }

                    return result;
                });

            var unsafeStatement = new GrammarDefinition("UnsafeStatement",
                rule: ToElement(UNSAFE) + blockStatement,
                createNode: node => new UnsafeStatement()
                {
                    Keyword = (AstToken) node.Children[0].Result,
                    Body = (BlockStatement) node.Children[1].Result
                });

            var fixedStatement = new GrammarDefinition("FixedStatement",
                rule: ToElement(FIXED) + ToElement(OPEN_PARENS)
                + variableDeclaration + ToElement(CLOSE_PARENS) + embeddedStatement,
                createNode: node =>
                {
                    var result = new FixedStatement();
                    result.Keyword = (AstToken) node.Children[0].Result;
                    result.LeftParenthese = (AstToken) node.Children[1].Result;

                    result.VariableDeclaration = (VariableDeclarationStatement) node.Children[2].Result;

                    result.RightParenthese = (AstToken) node.Children[3].Result;

                    var bodyNode = node.Children[4];
                    result.Body = (Statement) bodyNode.Result;
                    CheckForPossibleMistakenEmptyStatement(bodyNode);

                    return result;
                });

            embeddedStatement.Rule = emptyStatement
                                     | expressionStatement
                                     | blockStatement
                                     | selectionStatement
                                     | loopStatement
                                     | jumpStatement
                                     | lockStatement
                                     | usingStatement
                                     | yieldStatement
                                     | yieldBreakStatement
                                     | tryCatchStatement
                                     | unsafeStatement
                                     | fixedStatement
                ;


            statement.Rule = variableDeclarationStatement
                             | labelStatement
                             | embeddedStatement;
            ;
            #endregion

            #region Members

            var customAttribute = new GrammarDefinition("CustomAttribute",
                rule: namespaceOrTypeExpression
                | namespaceOrTypeExpression + ToElement(OPEN_PARENS) + argumentListOptional + ToElement(CLOSE_PARENS),
                createNode: node =>
                {
                    var result = new CustomAttribute();
                    result.Type = ((IConvertibleToType) node.Children[0].Result).ToTypeReference();

                    if (node.Children.Count > 1)
                    {
                        result.LeftParenthese = (AstToken) node.Children[1].Result;

                        if (node.Children[2].HasChildren)
                        {
                            foreach (var child in node.Children[2].Children[0].GetAllListAstNodes())
                            {
                                if (child is AstToken)
                                    result.AddChild(AstNodeTitles.ElementSeparator, child);
                                else
                                    result.Arguments.Add((Expression) child);
                            }
                        }

                        result.RightParenthese = (AstToken) node.Children[3].Result;

                    }
                    return result;
                });

            var customAttributeList = new GrammarDefinition("CustomAttributeList");
            customAttributeList.Rule = customAttribute | customAttributeList + ToElement(COMMA) + customAttribute;

            var customAttributePrefix = new GrammarDefinition("CustomAttributePrefix",
                rule: ToElement(ASSEMBLY) | ToElement(MODULE));

            var customAttributePrefixOptional = new GrammarDefinition("CustomAttributePrefixOptional",
                rule: null | customAttributePrefix + ToElement(COLON));

            var customAttributeSection = new GrammarDefinition("CustomAttributeSection",
                rule: ToElement(OPEN_BRACKET_EXPR) // HACK: use expression brackets instead to avoid conflicts.
                + customAttributePrefixOptional
                + customAttributeList 
                + ToElement(CLOSE_BRACKET),
                createNode: node =>
                {
                    var result = new CustomAttributeSection();
                    result.LeftBracket = (AstToken) node.Children[0].Result;

                    if (node.Children[1].Result != null)
                    {
                        result.VariantKeyword = (AstToken) node.Children[1].Result;
                        result.Variant = CSharpLanguage.SectionVariantFromString(result.VariantKeyword.Value);
                    }

                    foreach (var child in node.Children[2].GetAllListAstNodes())
                    {
                        if (child is AstToken)
                            result.AddChild(AstNodeTitles.ElementSeparator, child);
                        else
                            result.Attributes.Add((CustomAttribute) child);
                    }

                    result.RightBracket = (AstToken) node.Children[3].Result;
                    return result;
                });

            var customAttributeSectionList = new GrammarDefinition("CustomAttributeSectionList");
            customAttributeSectionList.Rule = customAttributeSection | customAttributeSectionList + customAttributeSection;

            var customAttributeSectionListOptional = new GrammarDefinition("CustomAttributeSectionListOptional",
                rule: null | customAttributeSectionList);

            var modifier = new GrammarDefinition("Modifier",
                rule: ToElement(PRIVATE)
                      | ToElement(PROTECTED)
                      | ToElement(INTERNAL)
                      | ToElement(PUBLIC)
                      | ToElement(STATIC)
                      | ToElement(ABSTRACT)
                      | ToElement(OVERRIDE)
                      | ToElement(PARTIAL)
                      | ToElement(CONST)
                      | ToElement(READONLY)
                      | ToElement(VIRTUAL)
                      | ToElement(SEALED)
                      | ToElement(UNSAFE)
                      | ToElement(FIXED)
                      | ToElement(ASYNC)
                      | ToElement(EXTERN),
                createNode: node => new ModifierElement(((AstToken) node.Children[0].Result).Value, node.Children[0].Range)
                {
                    Modifier = CSharpLanguage.ModifierFromString(((AstToken) node.Children[0].Result).Value)
                });

            var modifierList = new GrammarDefinition("ModifierList");
            modifierList.Rule = modifier | modifierList + modifier;
            var modifierListOptional = new GrammarDefinition("ModifierListOptional",
                rule: null | modifierList);

            var fieldDeclaration = new GrammarDefinition("FieldDeclaration",
                rule: customAttributeSectionListOptional
                      + modifierListOptional
                      + typeReference
                      + variableDeclaratorList
                      + ToElement(SEMICOLON),
                createNode: node =>
                {
                    var result = new FieldDeclaration();

                    if (node.Children[0].HasChildren)
                        result.CustomAttributeSections.AddRange(node.Children[0].Children[0].GetAllListAstNodes<CustomAttributeSection>());

                    if (node.Children[1].HasChildren)
                        result.ModifierElements.AddRange(node.Children[1].Children[0].GetAllListAstNodes<ModifierElement>());

                    result.FieldType = (TypeReference) node.Children[2].Result;

                    foreach (var subNode in node.Children[3].GetAllListAstNodes())
                    {
                        if (subNode is AstToken)
                            result.AddChild(AstNodeTitles.ElementSeparator, subNode);
                        else
                            result.Declarators.Add((VariableDeclarator) subNode);
                    }

                    result.AddChild(AstNodeTitles.Semicolon, node.Children[4].Result);
                    return result;
                });

            var parameterModifier = new GrammarDefinition("ParameterModifier",
                rule: null
                      | ToElement(THIS)
                      | ToElement(REF)
                      | ToElement(OUT)
                      | ToElement(PARAMS));
            var parameterDeclaration = new GrammarDefinition("ParameterDeclaration",
                rule: customAttributeSectionListOptional
                      + parameterModifier
                      + typeReference
                      + variableDeclarator,
                createNode: node =>
                {
                    var result = new ParameterDeclaration();

                    if (node.Children[0].HasChildren)
                    {
                        result.CustomAttributeSections.AddRange(
                            node.Children[0].Children[0].GetAllListAstNodes<CustomAttributeSection>());
                    }

                    result.ParameterModifierToken = (AstToken) (node.Children[1].HasChildren ? node.Children[1].Children[0].Result : null);
                    result.ParameterType = (TypeReference) node.Children[2].Result;
                    result.Declarator = (VariableDeclarator) node.Children[3].Result;
                    return result;
                });

            var parameterDeclarationList = new GrammarDefinition("ParameterDeclarationList");
            parameterDeclarationList.Rule = parameterDeclaration | parameterDeclarationList + ToElement(COMMA) + parameterDeclaration;
            var optionalParameterDeclarationList = new GrammarDefinition("OptionalParameterDeclarationList",
                rule: null | parameterDeclarationList);

            var constructorInitializerVariant = new GrammarDefinition("ConstructorInitializerVariant",
                rule: ToElement(THIS) | ToElement(BASE));
            var constructorInitializer = new GrammarDefinition("ConstructorInitializer",
                rule: constructorInitializerVariant
                      + ToElement(OPEN_PARENS)
                      + argumentListOptional
                      + ToElement(CLOSE_PARENS),
                createNode: node =>
                {
                    var result = new Members.ConstructorInitializer();
                    result.VariantToken = (AstToken) node.Children[0].Children[0].Result;
                    result.LeftParenthese = (AstToken) node.Children[1].Result;
                    if (node.Children[2].HasChildren)
                    {
                        foreach (var subNode in node.Children[2].Children[0].GetAllListAstNodes())
                        {
                            if (subNode is AstToken)
                                result.AddChild(AstNodeTitles.ElementSeparator, subNode);
                            else
                                result.Arguments.Add((Expression) subNode);
                        }
                    }
                    result.RightParenthese = (AstToken) node.Children[3].Result;
                    return result;
                });

            var optionalConstructorInitializerList = new GrammarDefinition("OptionalConstructorInitializer",
                rule: null | ToElement(COLON) + constructorInitializer);

            var constructorDeclaration = new GrammarDefinition("ConstructorDeclaration",
                rule: customAttributeSectionListOptional
                        + modifierListOptional
                        + ToElement(IDENTIFIER)
                        + ToElement(OPEN_PARENS)
                        + optionalParameterDeclarationList
                        + ToElement(CLOSE_PARENS)
                        + optionalConstructorInitializerList
                        + blockStatement,
                createNode: node =>
                {
                    var result = new Members.ConstructorDeclaration();

                    if (node.Children[0].HasChildren)
                        result.CustomAttributeSections.AddRange(node.Children[0].Children[0].GetAllListAstNodes<CustomAttributeSection>());

                    if (node.Children[1].HasChildren)
                        result.ModifierElements.AddRange(node.Children[1].Children[0].GetAllListAstNodes<ModifierElement>());

                    result.Identifier = ToIdentifier(node.Children[2].Result);
                    result.LeftParenthese = (AstToken) node.Children[3].Result;

                    if (node.Children[4].HasChildren)
                    {
                        foreach (var subNode in node.Children[4].Children[0].GetAllListAstNodes())
                        {
                            if (subNode is AstToken)
                                result.AddChild(AstNodeTitles.ElementSeparator, subNode);
                            else
                                result.Parameters.Add((ParameterDeclaration) subNode);
                        }
                    }

                    result.RightParenthese = (AstToken) node.Children[5].Result;

                    if (node.Children[6].HasChildren)
                    {
                        result.Colon = (AstToken) node.Children[6].Children[0].Result;
                        result.Initializer = (Members.ConstructorInitializer) node.Children[6].Children[1].Result;
                    }

                    result.Body = (BlockStatement) node.Children[7].Result;
                    return result;
                });

            var conversionOperator = new GrammarDefinition("ConversionOperator",
                rule: ToElement(IMPLICIT)
                      | ToElement(EXPLICIT));

            var conversionOperatorDeclaration = new GrammarDefinition("ConversionOperatorDeclaration",
                rule: customAttributeSectionListOptional
                      + modifierListOptional
                      + conversionOperator
                      + ToElement(OPERATOR)
                      + ToElement(IDENTIFIER)
                      + ToElement(OPEN_PARENS)
                      + optionalParameterDeclarationList
                      + ToElement(CLOSE_PARENS)
                      + blockStatement,
                createNode: node =>
                {
                    var result = new OperatorDeclaration();

                    if (node.Children[0].HasChildren)
                        result.CustomAttributeSections.AddRange(node.Children[0].Children[0].GetAllListAstNodes<CustomAttributeSection>());

                    if (node.Children[1].HasChildren)
                        result.ModifierElements.AddRange(node.Children[1].Children[0].GetAllListAstNodes<ModifierElement>());

                    result.Identifier = ToIdentifier(node.Children[2].Result);
                    result.OperatorType = CSharpLanguage.OperatorDeclarationTypeFromString(result.Identifier.Name);
                    result.OperatorKeyword = (AstToken) node.Children[3].Result;
                    result.ReturnType = ToTypeReference(ToIdentifier(node.Children[4].Result));
                    result.LeftParenthese = (AstToken)node.Children[5].Result;

                    if (node.Children[6].HasChildren)
                    {
                        foreach (var subNode in node.Children[6].Children[0].GetAllListAstNodes())
                        {
                            if (subNode is AstToken)
                                result.AddChild(AstNodeTitles.ElementSeparator, subNode);
                            else
                                result.Parameters.Add((ParameterDeclaration)subNode);
                        }
                    }

                    result.RightParenthese = (AstToken) node.Children[7].Result;
                    result.Body = (BlockStatement) node.Children[8].Result;

                    return result;
                });

            var overloadableOperator = new GrammarDefinition("OverloadableOperator",
                rule: ToElement(PLUS)
                      | ToElement(MINUS)
                      | ToElement(STAR)
                      | ToElement(DIV)
                      | ToElement(PERCENT)
                      | ToElement(BITWISE_AND)
                      | ToElement(BITWISE_OR)
                      | ToElement(CARRET)
                      | ToElement(OP_EQUALS)
                      | ToElement(OP_NOTEQUALS)
                      | ToElement(OP_GT)
                      | ToElement(OP_GE)
                      | ToElement(OP_LT)
                      | ToElement(OP_LE)
                      | ToElement(OP_SHIFT_LEFT)
                      | ToElement(OP_SHIFT_RIGHT)
                      | ToElement(TRUE)
                      | ToElement(FALSE)
                      | ToElement(BANG)
                      | ToElement(TILDE)
                      | ToElement(OP_INC)
                      | ToElement(OP_DEC));

            var arithmeticOperatorDeclaration = new GrammarDefinition("ArithmeticOperatorDeclaration",
                rule: customAttributeSectionListOptional
                      + modifierListOptional
                      + typeReference
                      + ToElement(OPERATOR)
                      + overloadableOperator
                      + ToElement(OPEN_PARENS)
                      + optionalParameterDeclarationList
                      + ToElement(CLOSE_PARENS)
                      + blockStatement,
                createNode: node =>
                {
                    var result = new OperatorDeclaration();

                    if (node.Children[0].HasChildren)
                        result.CustomAttributeSections.AddRange(node.Children[0].Children[0].GetAllListAstNodes<CustomAttributeSection>());

                    if (node.Children[1].HasChildren)
                        result.ModifierElements.AddRange(node.Children[1].Children[0].GetAllListAstNodes<ModifierElement>());

                    result.ReturnType = (TypeReference) node.Children[2].Result;
                    result.OperatorKeyword = (AstToken)node.Children[3].Result;
                    result.Identifier = ToIdentifier(node.Children[4].Result);

                    result.LeftParenthese = (AstToken)node.Children[5].Result;

                    if (node.Children[6].HasChildren)
                    {
                        foreach (var subNode in node.Children[6].Children[0].GetAllListAstNodes())
                        {
                            if (subNode is AstToken)
                                result.AddChild(AstNodeTitles.ElementSeparator, subNode);
                            else
                                result.Parameters.Add((ParameterDeclaration)subNode);
                        }
                    }

                    result.RightParenthese = (AstToken)node.Children[7].Result;

                    result.OperatorType = CSharpLanguage.OperatorDeclarationTypeFromString(result.Identifier.Name);
                    if (result.Parameters.Count == 2)
                    {
                        if (result.OperatorType == OperatorDeclarationType.Positive)
                            result.OperatorType = OperatorDeclarationType.Add;
                        else if (result.OperatorType == OperatorDeclarationType.Negative)
                            result.OperatorType = OperatorDeclarationType.Subtract;
                    }

                    result.Body = (BlockStatement)node.Children[8].Result;

                    return result;
                });

            var operatorDeclaration = new GrammarDefinition("OperatorDeclaration",
                rule: conversionOperatorDeclaration | arithmeticOperatorDeclaration);

            var methodDeclarationBody = new GrammarDefinition("MethodDeclarationBody",
                rule: ToElement(SEMICOLON) | blockStatement);

            var methodDeclaration = new GrammarDefinition("MethodDeclaration",
                rule: customAttributeSectionListOptional
                      + modifierListOptional
                      + typeReference
                      + ToElement(IDENTIFIER)
                      + ToElement(OPEN_PARENS)
                      + optionalParameterDeclarationList
                      + ToElement(CLOSE_PARENS)
                      + methodDeclarationBody,
                createNode: node =>
                {
                    var result = new MethodDeclaration();

                    if (node.Children[0].HasChildren)
                        result.CustomAttributeSections.AddRange(node.Children[0].Children[0].GetAllListAstNodes<CustomAttributeSection>());

                    if (node.Children[1].HasChildren)
                        result.ModifierElements.AddRange(node.Children[1].Children[0].GetAllListAstNodes<ModifierElement>());

                    result.ReturnType = (TypeReference) node.Children[2].Result;
                    result.Identifier = ToIdentifier(node.Children[3].Result);
                    result.LeftParenthese = (AstToken) node.Children[4].Result;

                    if (node.Children[5].HasChildren)
                    {
                        foreach (var subNode in node.Children[5].Children[0].GetAllListAstNodes())
                        {
                            if (subNode is AstToken)
                                result.AddChild(AstNodeTitles.ElementSeparator, subNode);
                            else
                                result.Parameters.Add((ParameterDeclaration) subNode);
                        }
                    }

                    result.RightParenthese = (AstToken) node.Children[6].Result;

                    var body = node.Children[7].Result;
                    if (body is AstToken)
                        result.AddChild(AstNodeTitles.Semicolon, (AstToken) body);
                    else
                        result.Body = (BlockStatement) body;
                    return result;
                });

            var eventDeclaration = new GrammarDefinition("EventDeclaration",
                rule: customAttributeSectionListOptional
                      + modifierListOptional
                      + ToElement(EVENT)
                      + typeReference
                      + variableDeclaratorList
                      + ToElement(SEMICOLON),
                createNode: node =>
                {
                    var result = new EventDeclaration();

                    if (node.Children[0].HasChildren)
                        result.CustomAttributeSections.AddRange(node.Children[0].Children[0].GetAllListAstNodes<CustomAttributeSection>());

                    if (node.Children[1].HasChildren)
                        result.ModifierElements.AddRange(node.Children[1].Children[0].GetAllListAstNodes<ModifierElement>());

                    result.EventKeyword = (AstToken) node.Children[2].Result;
                    result.EventType = (TypeReference) node.Children[3].Result;

                    foreach (var subNode in node.Children[4].GetAllListAstNodes())
                    {
                        if (subNode is AstToken)
                            result.AddChild(AstNodeTitles.ElementSeparator, subNode);
                        else
                            result.Declarators.Add((VariableDeclarator) subNode);
                    }

                    result.AddChild(AstNodeTitles.Semicolon, node.Children[5].Result);
                    return result;
                });

            var accessorKeyword = new GrammarDefinition("AccessorKeyword",
                rule: ToElement(GET)
                | ToElement(SET));
            var accessorBody = new GrammarDefinition("AccessorBody",
                rule: ToElement(SEMICOLON)
                      | blockStatement);

            var accessorDeclaration = new GrammarDefinition("AccessorDeclaration",
                rule: customAttributeSectionListOptional
                      + modifierListOptional
                      + accessorKeyword
                      + accessorBody,
                createNode: node =>
                {
                    var result = new AccessorDeclaration();

                    if (node.Children[0].HasChildren)
                        result.CustomAttributeSections.AddRange(node.Children[0].Children[0].GetAllListAstNodes<CustomAttributeSection>());

                    if (node.Children[1].HasChildren)
                        result.ModifierElements.AddRange(node.Children[1].Children[0].GetAllListAstNodes<ModifierElement>());

                    result.AccessorKeyword = (AstToken) node.Children[2].Children[0].Result;

                    var bodyNode = node.Children[3].Children[0].Result;
                    if (bodyNode is AstToken)
                        result.AddChild(AstNodeTitles.Semicolon, bodyNode);
                    else
                        result.Body = (BlockStatement) bodyNode;

                    return result;
                });

            var accessorDeclarationList = new GrammarDefinition("AccessorDeclarationList");
            accessorDeclarationList.Rule = accessorDeclaration | accessorDeclaration + accessorDeclaration;

            var propertyDeclaration = new GrammarDefinition("PropertyDeclaration",
                rule: customAttributeSectionListOptional
                      + modifierListOptional
                      + typeReference
                      + ToElement(IDENTIFIER)
                      + ToElement(OPEN_BRACE)
                      + accessorDeclarationList
                      + ToElement(CLOSE_BRACE),
                createNode: node =>
                {
                    var result = new PropertyDeclaration();

                    if (node.Children[0].HasChildren)
                        result.CustomAttributeSections.AddRange(node.Children[0].Children[0].GetAllListAstNodes<CustomAttributeSection>());

                    if (node.Children[1].HasChildren)
                        result.ModifierElements.AddRange(node.Children[1].Children[0].GetAllListAstNodes<ModifierElement>());

                    result.PropertyType = (TypeReference) node.Children[2].Result;
                    result.Identifier = ToIdentifier(node.Children[3].Result);
                    result.StartScope = node.Children[4].Result;

                    foreach (var accessor in node.Children[5].Children)
                    {
                        var declaration = (AccessorDeclaration) accessor.Result;
                        // TODO: detect duplicate accessor declarations.
                        switch (declaration.AccessorKeyword.Value)
                        {
                            case "get":
                                result.Getter = declaration;
                                break;
                            case "set":
                                result.Setter = declaration;
                                break;
                        }
                    }

                    result.EndScope = node.Children[6].Result;
                    return result;
                });

            var memberDeclaration = new GrammarDefinition("MemberDeclaration");
            var memberDeclarationList = new GrammarDefinition("MemberDeclarationList");
            memberDeclarationList.Rule = memberDeclaration | memberDeclarationList + memberDeclaration;
            var memberDeclarationListOptional = new GrammarDefinition("MemberDeclarationListOptional");
            memberDeclarationListOptional.Rule = null | memberDeclarationList;

            var baseTypeList = new GrammarDefinition("BaseTypeList");
            baseTypeList.Rule = typeReference | baseTypeList + ToElement(COMMA) + typeReference;

            var optionalBaseTypeList = new GrammarDefinition("OptionalBaseTypeList");
            optionalBaseTypeList.Rule = null | ToElement(COLON) + baseTypeList;

            var typeVariantKeyword = new GrammarDefinition("TypeVariantKeyword",
                rule: ToElement(CLASS)
                      | ToElement(STRUCT)
                      | ToElement(INTERFACE)
                      | ToElement(ENUM));
            var typeDeclaration = new GrammarDefinition("TypeDeclaration",
                rule: customAttributeSectionListOptional
                      + modifierListOptional
                      + typeVariantKeyword
                      + ToElement(IDENTIFIER)
                      + optionalBaseTypeList
                      + ToElement(OPEN_BRACE)
                      + memberDeclarationListOptional
                      + ToElement(CLOSE_BRACE),
                createNode: node =>
                {
                    var result = new TypeDeclaration();

                    if (node.Children[0].HasChildren)
                        result.CustomAttributeSections.AddRange(node.Children[0].Children[0].GetAllListAstNodes<CustomAttributeSection>());

                    if (node.Children[1].HasChildren)
                        result.ModifierElements.AddRange(node.Children[1].Children[0].GetAllListAstNodes<ModifierElement>());

                    var variantToken = (AstToken) node.Children[2].Children[0].Result;
                    result.TypeVariant = CSharpLanguage.TypeVariantFromString(variantToken.Value);
                    result.TypeVariantToken = variantToken;
                    result.Identifier = ToIdentifier(node.Children[3].Result);

                    if (node.Children[4].HasChildren)
                    {
                        result.AddChild(AstNodeTitles.Colon, node.Children[4].Children[0].Result);

                        foreach (var child in node.Children[4].Children[1].GetAllListAstNodes())
                        {
                            if (child is AstToken)
                                result.AddChild(AstNodeTitles.ElementSeparator, child);
                            else
                                result.BaseTypes.Add((TypeReference) child);
                        }
                    }

                    result.StartScope = node.Children[5].Result;

                    if (node.Children[6].HasChildren)
                    {
                        result.Members.AddRange(node.Children[6].Children[0].GetAllListAstNodes<MemberDeclaration>());
                    }

                    result.EndScope = node.Children[7].Result;
                    return result;
                });

            memberDeclaration.Rule = methodDeclaration
                                     | constructorDeclaration
                                     | operatorDeclaration
                                     | propertyDeclaration
                                     | eventDeclaration
                                     | fieldDeclaration
                                     | typeDeclaration
                                    ;

            var typeOrNamespaceDeclarationList = new GrammarDefinition("TypeOrNamespaceDeclarationList");
            var typeOrNamespaceDeclarationListOptional = new GrammarDefinition("TypeOrNamespaceDeclarationListOptional",
                rule: null | typeOrNamespaceDeclarationList);

            var namespaceDeclaration = new GrammarDefinition("NamespaceDeclaration",
                rule: ToElement(NAMESPACE)
                      + typeNameExpression
                      + ToElement(OPEN_BRACE)
                      + usingDirectiveListOptional
                      + typeOrNamespaceDeclarationListOptional
                      + ToElement(CLOSE_BRACE),
                createNode: node =>
                {
                    var result = new NamespaceDeclaration();
                    result.Keyword = (AstToken) node.Children[0].Result;
                    result.Identifier = ((IConvertibleToIdentifier) node.Children[1].Result).ToIdentifier();
                    result.StartScope = node.Children[2].Result;

                    if (node.Children[3].HasChildren)
                    {
                        result.UsingDirectives.AddRange(node.Children[3].Children[0].GetAllListAstNodes<UsingDirective>());
                    }

                    if (node.Children[4].HasChildren)
                    {
                        foreach (var subNode in node.Children[4].Children[0].GetAllListAstNodes())
                        {
                            var type = subNode as TypeDeclaration;
                            if (type != null)
                                result.Types.Add(type);
                            else
                                result.Namespaces.Add((NamespaceDeclaration) subNode);
                        }
                    }

                    result.EndScope = node.Children[5].Result;

                    return result;
                });

            var typeOrNamespaceDeclaration = new GrammarDefinition("TypeOrNamespaceDeclaration",
                rule: namespaceDeclaration
                      | typeDeclaration);
            typeOrNamespaceDeclarationList.Rule = typeOrNamespaceDeclaration
                                                  | typeOrNamespaceDeclarationList
                                                  + typeOrNamespaceDeclaration;

            #endregion

            #region Initialize definitions

            var variableInitializerList = new GrammarDefinition("VariableInitializerList");
            variableInitializerList.Rule = variableInitializer
                                           | variableInitializerList
                                           + ToElement(COMMA)
                                           + variableInitializer;
            var variableInitializerListOptional = new GrammarDefinition("VariableInitializerListOptional",
                rule: null | variableInitializerList);

            arrayInitializer.Rule = ToElement(OPEN_BRACE)
                                    + variableInitializerListOptional
                                    + ToElement(CLOSE_BRACE)
                                    | ToElement(OPEN_BRACE)
                                    + variableInitializerList
                                    + ToElement(COMMA)
                                    + ToElement(CLOSE_BRACE);

            arrayInitializer.ComputeResult = node =>
            {
                var result = new ArrayInitializer();
                result.OpeningBrace = node.Children[0].Result;

                ParserNode initializersNode = null;
                if (node.Children.Count == 4)
                {
                    initializersNode = node.Children[1];
                }
                else
                {
                    if (node.Children[1].HasChildren)
                        initializersNode = node.Children[1].Children[0];
                }

                if (initializersNode != null)
                {
                    foreach (var element in initializersNode.GetAllListAstNodes())
                    {
                        if (element is AstToken)
                            result.AddChild(AstNodeTitles.ElementSeparator, element);
                        else
                            result.Elements.Add((Expression) element);
                    }
                }

                if (node.Children.Count == 4)
                    result.AddChild(AstNodeTitles.ElementSeparator, node.Children[2].Result);
                result.ClosingBrace = node.Children[node.Children.Count - 1].Result;
                return result;
            };

            variableInitializer.Rule = expression
                                       | arrayInitializer
                ;

            var variableType = new GrammarDefinition("VariableType");
            variableType.Rule = typeNameExpression | variableType + rankSpecifier | variableType + ToElement(STAR);
            variableType.ComputeResult = node =>
            {
                var type = ToTypeReference((IConvertibleToType) node.Children[0].Result);
                if (node.Children.Count > 1)
                {
                    var specifier = node.Children[1].Result as ArrayTypeRankSpecifier;
                    if (specifier != null)
                    {
                        type = new ArrayTypeReference(type, specifier);
                    }
                    else
                    {
                        type = new PointerTypeReference(type)
                        {
                            PointerToken = (AstToken) node.Children[1].Result
                        };
                    }
                }
                return type;
            };

            // Types are recognized as expressions to prevent a conflict in the grammar.
            // TODO: also support array and pointer types.

            variableDeclaration.Rule =
                variableType
                + variableDeclaratorList;
            
            variableDeclaration.ComputeResult = node =>
            {
                var result = new VariableDeclarationStatement();
                result.VariableType = ToTypeReference((IConvertibleToType)node.Children[0].Result);

                foreach (var subNode in node.Children[1].GetAllListAstNodes())
                {
                    if (subNode is AstToken)
                        result.AddChild(AstNodeTitles.ElementSeparator, subNode);
                    else
                        result.Declarators.Add((VariableDeclarator) subNode);
                }

                return result;
            };

            statementList.Rule = statement | statementList + statement;

            #endregion

            #region Root compilation unit

            var usingNamespaceDirective = new GrammarDefinition("UsingNamespaceDirective",
                rule: ToElement(USING)
                      + namespaceOrTypeExpression
                      + ToElement(SEMICOLON),
                createNode: node =>
                {
                    var result = new UsingNamespaceDirective();

                    result.UsingKeyword = (AstToken) node.Children[0].Result;
                    result.NamespaceIdentifier = ((IConvertibleToIdentifier) node.Children[1].Result).ToIdentifier();
                    result.AddChild(AstNodeTitles.Semicolon, node.Children[2].Result);

                    return result;
                });

            var usingAliasDirective = new GrammarDefinition("UsingAliasDirective",
                rule: ToElement(USING)
                      + ToElement(IDENTIFIER)
                      + ToElement(EQUALS)
                      + typeReference
                      + ToElement(SEMICOLON),
                createNode: node =>
                {
                    var result = new UsingAliasDirective
                    {
                        UsingKeyword = (AstToken) node.Children[0].Result,
                        AliasIdentifier = ToIdentifier(node.Children[1].Result),
                        OperatorToken = (AstToken) node.Children[2].Result,
                        TypeImport = (TypeReference) node.Children[3].Result
                    };
                    result.AddChild(AstNodeTitles.Semicolon, node.Children[4].Result);
                    return result;
                });

            var usingDirective = new GrammarDefinition("UsingNamespaceDirective",
                rule: usingNamespaceDirective | usingAliasDirective);

            var usingDirectiveList = new GrammarDefinition("UsingDirectiveList");
            usingDirectiveList.Rule = usingDirective | usingDirectiveList + usingDirective;
            usingDirectiveListOptional.Rule = null | usingDirectiveList;

            var compilationUnit = new GrammarDefinition("CompilationUnit",
                rule: usingDirectiveListOptional
                + typeOrNamespaceDeclarationListOptional,
                createNode: node =>
                {
                    var result = new CompilationUnit();

                    if (node.Children[0].HasChildren)
                    {
                        result.UsingDirectives.AddRange(node.Children[0].Children[0].GetAllListAstNodes<UsingDirective>());
                    }

                    if (node.Children[1].HasChildren)
                    {
                        foreach (var subNode in node.Children[1].Children[0].GetAllListAstNodes())
                        {
                            var typeDecl = subNode as TypeDeclaration;
                            if (typeDecl == null)
                                result.Namespaces.Add((NamespaceDeclaration) subNode);
                            else
                                result.Types.Add(typeDecl);
                        }
                    }

                    return result;
                });

            #endregion

            RootDefinitions.Add(DefaultRoot = compilationUnit);
            RootDefinitions.Add(MemberDeclarationRule = memberDeclaration);
            RootDefinitions.Add(StatementRule = statement);
        }
        public override void VisitEventDeclaration(EventDeclaration eventDeclaration)
        {
            FixAttributesAndDocComment(eventDeclaration);

            foreach (var m in eventDeclaration.ModifierTokens) {
                ForceSpacesAfter(m, true);
            }

            ForceSpacesBeforeRemoveNewLines(eventDeclaration.EventToken.GetNextSibling(NoWhitespacePredicate), true);
            eventDeclaration.ReturnType.AcceptVisitor(this);
            ForceSpacesAfter(eventDeclaration.ReturnType, true);
            /*
            var lastLoc = eventDeclaration.StartLocation;
            curIndent.Push(IndentType.Block);
            foreach (var initializer in eventDeclaration.Variables) {
                if (lastLoc.Line != initializer.StartLocation.Line) {
                    FixStatementIndentation(initializer.StartLocation);
                    lastLoc = initializer.StartLocation;
                }
                initializer.AcceptVisitor(this);
            }
            curIndent.Pop ();
            */
            FixSemicolon(eventDeclaration.SemicolonToken);
        }
		public virtual void VisitEventDeclaration (EventDeclaration eventDeclaration)
		{
			VisitChildren (eventDeclaration);
		}
Пример #56
0
 EntityDeclaration ConvertEvent(IEvent ev)
 {
     if (this.UseCustomEvents) {
         CustomEventDeclaration decl = new CustomEventDeclaration();
         decl.Modifiers = GetMemberModifiers(ev);
         decl.ReturnType = ConvertType(ev.ReturnType);
         decl.Name = ev.Name;
         decl.AddAccessor    = ConvertAccessor(ev.AddAccessor, ev.Accessibility);
         decl.RemoveAccessor = ConvertAccessor(ev.RemoveAccessor, ev.Accessibility);
         return decl;
     } else {
         EventDeclaration decl = new EventDeclaration();
         decl.Modifiers = GetMemberModifiers(ev);
         decl.ReturnType = ConvertType(ev.ReturnType);
         decl.Variables.Add(new VariableInitializer(ev.Name));
         return decl;
     }
 }
Пример #57
0
			public override void Visit (EventField e)
			{
				EventDeclaration newEvent = new EventDeclaration ();
				
				var location = LocationsBag.GetMemberLocation (e);
				AddModifiers (newEvent, location);
				
				if (location != null)
					newEvent.AddChild (new CSharpTokenNode (Convert (location[0]), "event".Length), EventDeclaration.Roles.Keyword);
				newEvent.AddChild ((INode)e.TypeName.Accept (this), AbstractNode.Roles.ReturnType);
				newEvent.AddChild (new Identifier (e.MemberName.Name, Convert (e.MemberName.Location)), EventDeclaration.Roles.Identifier);
				if (location != null)
					newEvent.AddChild (new CSharpTokenNode (Convert (location[1]), ";".Length), EventDeclaration.Roles.Semicolon);
				
				typeStack.Peek ().AddChild (newEvent, TypeDeclaration.Roles.Member);
			}
Пример #58
0
        public virtual string GetEventName(EventDeclaration evt)
        {
            if (!string.IsNullOrEmpty(evt.Name))
            {
                return evt.Name;
            }

            if (evt.Variables.Count > 0)
            {
                return evt.Variables.First().Name;
            }

            return null;
        }
Пример #59
0
		public void VisitEventDeclaration(EventDeclaration eventDeclaration)
		{
			StartNode(eventDeclaration);
			WriteAttributes(eventDeclaration.Attributes);
			WriteModifiers(eventDeclaration.ModifierTokens);
			WriteKeyword(EventDeclaration.EventKeywordRole);
			eventDeclaration.ReturnType.AcceptVisitor(this);
			Space();
			WriteCommaSeparatedList(eventDeclaration.Variables);
			Semicolon();
			EndNode(eventDeclaration);
		}
Пример #60
0
 public override void Visit(EventDeclaration node) { this.action(node); }