public override void VisitUnaryOperatorExpression (UnaryOperatorExpression unaryOperatorExpression)
			{
				base.VisitUnaryOperatorExpression (unaryOperatorExpression);

				if (unaryOperatorExpression.Operator != UnaryOperatorType.Not)
					return;

				var expr = unaryOperatorExpression.Expression;
				while (expr != null && expr is ParenthesizedExpression)
					expr = ((ParenthesizedExpression)expr).Expression;

				var binaryOperatorExpr = expr as BinaryOperatorExpression;
				if (binaryOperatorExpr == null)
					return;

				var negatedOp = CSharpUtil.NegateRelationalOperator(binaryOperatorExpr.Operator);
				if (negatedOp == BinaryOperatorType.Any)
					return;

				if (IsFloatingPoint (binaryOperatorExpr.Left) || IsFloatingPoint (binaryOperatorExpr.Right)) {
					if (negatedOp != BinaryOperatorType.Equality && negatedOp != BinaryOperatorType.InEquality)
						return;
				}

				AddIssue (unaryOperatorExpression, ctx.TranslateString ("Simplify negative relational expression"),
					script => script.Replace (unaryOperatorExpression,
						new BinaryOperatorExpression (binaryOperatorExpr.Left.Clone (), negatedOp,
					          	binaryOperatorExpr.Right.Clone ())));
			}
		public override object VisitUnaryOperatorExpression(UnaryOperatorExpression unaryOperatorExpression, object data)
		{
			if (unaryOperatorExpression.Op == UnaryOperatorType.Not) {
				return unaryOperatorExpression.Expression.AcceptVisitor(this, data) == SymbolDefined ? null : SymbolDefined;
			} else {
				return null;
			}
		}
		public void TrickyCast1()
		{
			Expression expr = new UnaryOperatorExpression(
				UnaryOperatorType.Minus, new IdentifierExpression("a")
			).CastTo(new PrimitiveType("int"));
			
			Assert.AreEqual("(int)-a", InsertRequired(expr));
			Assert.AreEqual("(int)(-a)", InsertReadable(expr));
		}
		public void TrickyCast3()
		{
			Expression expr = new UnaryOperatorExpression(
				UnaryOperatorType.Not, new IdentifierExpression("a")
			).CastTo(new SimpleType("MyType"));
			
			Assert.AreEqual("(MyType)!a", InsertRequired(expr));
			Assert.AreEqual("(MyType)(!a)", InsertReadable(expr));
		}
        public void DoubleNegation()
        {
            Expression expr = new UnaryOperatorExpression(
                UnaryOperatorType.Minus,
                new UnaryOperatorExpression(UnaryOperatorType.Minus, new IdentifierExpression("a"))
            );

            Assert.AreEqual("- -a", InsertRequired(expr));
            Assert.AreEqual("-(-a)", InsertReadable(expr));
        }
 public override void VisitUnaryOperatorExpression(UnaryOperatorExpression unaryOperatorExpression)
 {
     if (unaryOperatorExpression.Operator == UnaryOperatorType.Await) {
         _errorReporter.Message(7998, unaryOperatorExpression.GetRegion(), "await");
         _result = false;
     }
     else {
         base.VisitUnaryOperatorExpression(unaryOperatorExpression);
     }
 }
			static VariableInitializer GetControlVariable(VariableDeclarationStatement variableDecl,
														  UnaryOperatorExpression condition)
			{
				var controlVariables = variableDecl.Variables.Where (
					v =>
					{
						var identifier = new IdentifierExpression (v.Name);
						return condition.Expression.Match (identifier).Success;
					}).ToList ();
				return controlVariables.Count == 1 ? controlVariables [0] : null;
			}
Exemple #8
0
        public override void VisitUnaryOperatorExpression(UnaryOperatorExpression unaryOperatorExpression)
        {
            if (unaryOperatorExpression.Operator == UnaryOperatorType.Await)
            {
                var tryBlock = unaryOperatorExpression.GetParent<TryCatchStatement>();

                if (tryBlock != null)
                {
                    this.Found = true;
                }
            }

            base.VisitUnaryOperatorExpression(unaryOperatorExpression);
        }
Exemple #9
0
        public static dynamic GetValueFromUnaryExpression(UnaryOperatorExpression expr)
        {
            var value = GetValueFromExpression(expr.Expression);
            if (value == null)
                return null;

            switch (expr.Operator)
            {
                case UnaryOperatorType.Not:
                    return !value;
                case UnaryOperatorType.Minus:
                    return -value;
                case UnaryOperatorType.Plus:
                    return +value;
                default:
                    return null;
            }
        }
		public override IEnumerable<CodeAction> GetActions(RefactoringContext context)
		{
			var node = context.GetNode<BinaryOperatorExpression>();
			if (node == null || 
			    (node.Operator != BinaryOperatorType.Equality && node.Operator != BinaryOperatorType.InEquality) ||
			    !node.OperatorToken.Contains(context.Location))
				yield break;

			yield return new CodeAction(
				context.TranslateString("Use 'Equals'"),
				script => {
					Expression expr = new InvocationExpression(GenerateTarget(context, node), node.Left.Clone(), node.Right.Clone());
					if (node.Operator == BinaryOperatorType.InEquality)
						expr = new UnaryOperatorExpression(UnaryOperatorType.Not, expr);
					script.Replace(node, expr);
				}, 
				node.OperatorToken
			);
		}
			public override void VisitBinaryOperatorExpression (BinaryOperatorExpression binaryOperatorExpression)
			{
				base.VisitBinaryOperatorExpression (binaryOperatorExpression);

				var match = pattern.Match (binaryOperatorExpression);
				if (!match.Success)
					return;

				AddIssue (binaryOperatorExpression, ctx.TranslateString ("Simplify boolean comparison"), scrpit => {
					var expr = match.Get<Expression> ("expr").First ().Clone ();
					var boolConstant = (bool)match.Get<PrimitiveExpression> ("const").First ().Value;
					if ((binaryOperatorExpression.Operator == BinaryOperatorType.InEquality && boolConstant) ||
						(binaryOperatorExpression.Operator == BinaryOperatorType.Equality && !boolConstant)) {
						expr = new UnaryOperatorExpression (UnaryOperatorType.Not, expr);
						expr.AcceptVisitor (insertParenthesesVisitor);
					}
					scrpit.Replace (binaryOperatorExpression, expr);
				});
			}
			public override void VisitUnaryOperatorExpression (UnaryOperatorExpression unaryOperatorExpression)
			{
				base.VisitUnaryOperatorExpression (unaryOperatorExpression);

				if (unaryOperatorExpression.Operator != UnaryOperatorType.Not)
					return;

				var innerUnaryOperatorExpr = 
					RemoveParentheses (unaryOperatorExpression.Expression) as UnaryOperatorExpression;
				if (innerUnaryOperatorExpr == null || innerUnaryOperatorExpr.Operator != UnaryOperatorType.Not)
					return;

				var expression = RemoveParentheses (innerUnaryOperatorExpr.Expression);
				if (expression.IsNull)
					return;

				AddIssue (unaryOperatorExpression, ctx.TranslateString ("Remove double negation"),
					script => script.Replace (unaryOperatorExpression, expression.Clone ()));
			}
        protected bool ResolveOperator(UnaryOperatorExpression unaryOperatorExpression, OperatorResolveResult orr)
        {
            if (orr != null && orr.UserDefinedOperatorMethod != null)
            {
                var method = orr.UserDefinedOperatorMethod;
                var inline = this.Emitter.GetInline(method);

                if (!string.IsNullOrWhiteSpace(inline))
                {
                    new InlineArgumentsBlock(this.Emitter, new ArgumentsInfo(this.Emitter, unaryOperatorExpression, orr, method), inline).Emit();
                    return true;
                }
                else
                {
                    if (orr.IsLiftedOperator)
                    {
                        this.Write(Bridge.Translator.Emitter.ROOT + ".Nullable.lift(");
                    }

                    this.Write(BridgeTypes.ToJsName(method.DeclaringType, this.Emitter));
                    this.WriteDot();

                    this.Write(OverloadsCollection.Create(this.Emitter, method).GetOverloadName());

                    if (orr.IsLiftedOperator)
                    {
                        this.WriteComma();
                    }
                    else
                    {
                        this.WriteOpenParentheses();
                    }

                    new ExpressionListBlock(this.Emitter, new Expression[] { unaryOperatorExpression.Expression }, null).Emit();
                    this.WriteCloseParentheses();

                    return true;
                }
            }

            return false;
        }
		public override System.Collections.Generic.IEnumerable<CodeAction> GetActions(RefactoringContext context)
		{
			Expression expr = null;
			AstNode token;
			if (!NegateRelationalExpressionAction.GetLogicalExpression (context, out expr, out token))
				yield break;

			var uOp = expr as UnaryOperatorExpression;
			if (uOp != null) {
				yield return new CodeAction(
					string.Format(context.TranslateString("Invert '{0}'"), expr),
					script => {
						script.Replace(uOp, CSharpUtil.InvertCondition(CSharpUtil.GetInnerMostExpression(uOp.Expression)));
					}, token
				);	
				yield break;
			}

			var negativeExpression = CSharpUtil.InvertCondition(expr);
			if (expr.Parent is ParenthesizedExpression && expr.Parent.Parent is UnaryOperatorExpression) {
				var unaryOperatorExpression = expr.Parent.Parent as UnaryOperatorExpression;
				if (unaryOperatorExpression.Operator == UnaryOperatorType.Not) {
					yield return new CodeAction(
						string.Format(context.TranslateString("Invert '{0}'"), unaryOperatorExpression),
						script => {
							script.Replace(unaryOperatorExpression, negativeExpression);
						}, token
					);	
					yield break;
				}
			}
			var newExpression = new UnaryOperatorExpression(UnaryOperatorType.Not, new ParenthesizedExpression(negativeExpression));
			yield return new CodeAction(
				string.Format(context.TranslateString("Invert '{0}'"), expr),
				script => {
					script.Replace(expr, newExpression);
				}, token
			);
		}
			public override void VisitBinaryOperatorExpression (BinaryOperatorExpression binaryOperatorExpression)
			{
				base.VisitBinaryOperatorExpression (binaryOperatorExpression);

				var match = pattern.Match (binaryOperatorExpression);
				if (!match.Success)
					return;
				var expr = match.First<Expression>("expr");
				// check if expr is of boolean type
				var exprType = ctx.Resolve (expr).Type.GetDefinition ();
				if (exprType == null || exprType.KnownTypeCode != KnownTypeCode.Boolean)
					return;

				AddIssue (binaryOperatorExpression, ctx.TranslateString ("Simplify boolean comparison"), scrpit => {
                    var boolConstant = (bool)match.First<PrimitiveExpression>("const").Value;
					if ((binaryOperatorExpression.Operator == BinaryOperatorType.InEquality && boolConstant) ||
						(binaryOperatorExpression.Operator == BinaryOperatorType.Equality && !boolConstant)) {
						expr = new UnaryOperatorExpression (UnaryOperatorType.Not, expr.Clone());
						expr.AcceptVisitor (insertParenthesesVisitor);
					}
					scrpit.Replace (binaryOperatorExpression, expr);
				});
			}
Exemple #16
0
 public virtual Expression visit(UnaryOperatorExpression expression)
 {
     return(visit((Expression)expression));
 }
		public void PostPre()
		{
			Expression expr = new UnaryOperatorExpression(
				UnaryOperatorType.PostIncrement,
				new UnaryOperatorExpression(
					UnaryOperatorType.Increment,
					new IdentifierExpression("a")
				)
			);
			
			Assert.AreEqual("(++a)++", InsertRequired(expr));
			Assert.AreEqual("(++a)++", InsertReadable(expr));
		}
Exemple #18
0
        public override object VisitUnaryOperatorExpression(UnaryOperatorExpression unary, object data)
        {
            // Remove double negation
            // !!a
            if (unary.Operator == UnaryOperatorType.Not &&
                unary.Expression is UnaryOperatorExpression &&
                (unary.Expression as UnaryOperatorExpression).Operator == UnaryOperatorType.Not)
            {
                AstNode newNode = (unary.Expression as UnaryOperatorExpression).Expression;
                unary.ReplaceWith(newNode);
                return(newNode.AcceptVisitor(this, data));
            }

            // Push through binary operation
            // !((a) op (b))
            BinaryOperatorExpression binaryOp = unary.Expression as BinaryOperatorExpression;

            if (unary.Operator == UnaryOperatorType.Not && binaryOp != null)
            {
                bool successful = true;
                switch (binaryOp.Operator)
                {
                case BinaryOperatorType.Equality:
                    binaryOp.Operator = BinaryOperatorType.InEquality;
                    break;

                case BinaryOperatorType.InEquality:
                    binaryOp.Operator = BinaryOperatorType.Equality;
                    break;

                case BinaryOperatorType.GreaterThan:                         // TODO: these are invalid for floats (stupid NaN)
                    binaryOp.Operator = BinaryOperatorType.LessThanOrEqual;
                    break;

                case BinaryOperatorType.GreaterThanOrEqual:
                    binaryOp.Operator = BinaryOperatorType.LessThan;
                    break;

                case BinaryOperatorType.LessThanOrEqual:
                    binaryOp.Operator = BinaryOperatorType.GreaterThan;
                    break;

                case BinaryOperatorType.LessThan:
                    binaryOp.Operator = BinaryOperatorType.GreaterThanOrEqual;
                    break;

                default:
                    successful = false;
                    break;
                }
                if (successful)
                {
                    unary.ReplaceWith(binaryOp);
                    return(binaryOp.AcceptVisitor(this, data));
                }

                successful = true;
                switch (binaryOp.Operator)
                {
                case BinaryOperatorType.ConditionalAnd:
                    binaryOp.Operator = BinaryOperatorType.ConditionalOr;
                    break;

                case BinaryOperatorType.ConditionalOr:
                    binaryOp.Operator = BinaryOperatorType.ConditionalAnd;
                    break;

                default:
                    successful = false;
                    break;
                }
                if (successful)
                {
                    binaryOp.Left.ReplaceWith(e => new UnaryOperatorExpression(UnaryOperatorType.Not, e));
                    binaryOp.Right.ReplaceWith(e => new UnaryOperatorExpression(UnaryOperatorType.Not, e));
                    unary.ReplaceWith(binaryOp);
                    return(binaryOp.AcceptVisitor(this, data));
                }
            }
            return(base.VisitUnaryOperatorExpression(unary, data));
        }
Exemple #19
0
 IEnumerable <Syntax> IAstVisitor <ILTranslationContext, IEnumerable <Syntax> > .VisitUnaryOperatorExpression(UnaryOperatorExpression unaryOperatorExpression, ILTranslationContext data)
 => OnVisiting(data, unaryOperatorExpression, VisitingUnaryOperatorExpression)
 ?? OnVisited(data, unaryOperatorExpression, VisitedUnaryOperatorExpression, TranslateUnaryOperatorExpression(unaryOperatorExpression, data));
Exemple #20
0
        public Ust VisitExpression(JavaParser.ExpressionContext context)
        {
            var        textSpan       = context.GetTextSpan();
            var        child0Terminal = context.GetChild(0) as ITerminalNode;
            Expression target;
            Expression result;

            if (child0Terminal != null)
            {
                switch (child0Terminal.Symbol.Type)
                {
                case JavaParser.NEW:
                    result = (Expression)Visit(context.creator());
                    return(result);

                case JavaParser.LPAREN:     // '(' type ')' expression
                    var type = (TypeToken)Visit(context.typeType());
                    target = (Expression)Visit(context.expression(0));
                    result = new CastExpression(type, target, textSpan);
                    return(result);

                default:     // unary operator ('+', '-', '++', '--', '~', '!')
                    UnaryOperator op        = UnaryOperatorLiteral.PrefixTextUnaryOperator[child0Terminal.GetText()];
                    var           opLiteral = new UnaryOperatorLiteral(op, child0Terminal.GetTextSpan());
                    target = (Expression)Visit(context.expression(0));
                    result = new UnaryOperatorExpression(opLiteral, target, textSpan);
                    return(result);
                }
            }

            ArgsUst args;
            var     child1Terminal = context.GetChild(1) as ITerminalNode;

            if (child1Terminal != null)
            {
                switch (child1Terminal.Symbol.Type)
                {
                case JavaParser.DOT:     // '.'
                    target = (Expression)Visit(context.expression(0));

                    if (context.methodCall() != null)
                    {
                        var invocation = (InvocationExpression)Visit(context.methodCall());
                        return(new InvocationExpression(
                                   new MemberReferenceExpression(target, invocation.Target, target.TextSpan.Union(invocation.Target.TextSpan)),
                                   invocation.Arguments,
                                   textSpan));
                    }

                    // TODO: implement base processing

                    Expression rightPart = null;
                    if (context.IDENTIFIER() != null)
                    {
                        rightPart = (IdToken)Visit(context.IDENTIFIER());
                    }
                    else if (context.THIS() != null)
                    {
                        rightPart = new ThisReferenceToken(context.THIS().GetTextSpan());
                    }

                    if (rightPart != null)
                    {
                        return(new MemberReferenceExpression(target, rightPart, textSpan));
                    }

                    if (context.innerCreator() != null)
                    {
                        return(Visit(context.innerCreator()));
                    }

                    if (context.explicitGenericInvocation() != null)
                    {
                        return(VisitChildren(context.explicitGenericInvocation()).ToExpressionIfRequired());
                    }

                    break;

                case JavaParser.LBRACK:     // '['
                    target = (Expression)Visit(context.expression(0));
                    Expression expr = (Expression)Visit(context.expression(1));
                    args = new ArgsUst(new Expression[] { expr }, expr.TextSpan);

                    result = new IndexerExpression(target, args, textSpan);
                    return(result);

                case JavaParser.INSTANCEOF:     // x instanceof y -> (y)x != null
                    var expression = (Expression)Visit(context.expression(0));
                    var type       = (TypeToken)Visit(context.typeType());
                    result = new BinaryOperatorExpression(context.GetTextSpan())
                    {
                        Left     = new CastExpression(type, expression, context.GetTextSpan()),
                        Operator = new BinaryOperatorLiteral(BinaryOperator.NotEqual, default),
                        Right    = new NullLiteral(default),
                        Root     = root
                    };
                    return(result);

                case JavaParser.QUESTION:     // '?'
                    var condition = (Expression)Visit(context.expression(0));
                    var trueExpr  = (Expression)Visit(context.expression(1));
                    var falseExpr = (Expression)Visit(context.expression(2));

                    result = new ConditionalExpression(condition, trueExpr, falseExpr, textSpan);
                    return(result);

                case JavaParser.COLONCOLON:
                    return(VisitChildren(context));

                default:     // binary operator
                    var left = (Expression)Visit(context.expression(0));
                    JavaParser.ExpressionContext expr1 = context.expression(1);

                    if (expr1 != null)
                    {
                        string opText = string.Concat(context.children.Skip(1).Take(context.children.Count - 2));
                        var    right  = (Expression)Visit(expr1);

                        // TODO: fix via grammar refactoring (alternative labels).
                        if (opText == "=" ||
                            (opText.EndsWith("=") && BinaryOperatorLiteral.TextBinaryOperator.ContainsKey(opText.Remove(opText.Length - 1))))
                        {
                            result = UstUtils.CreateAssignExpr(left, right, context.GetTextSpan(),
                                                               opText, child1Terminal.GetTextSpan());
                        }
                        else
                        {
                            BinaryOperator op        = BinaryOperatorLiteral.TextBinaryOperator[opText];
                            var            opLiteral = new BinaryOperatorLiteral(op, child1Terminal.GetTextSpan());
                            result = new BinaryOperatorExpression(left, opLiteral, right, textSpan);
                        }
                    }
                    else
                    {
                        // post increment or decrement.
                        UnaryOperator op        = UnaryOperatorLiteral.PostfixTextUnaryOperator[context.postfix.Text];
                        var           opLiteral = new UnaryOperatorLiteral(op, child1Terminal.GetTextSpan());

                        result = new UnaryOperatorExpression(opLiteral, left, textSpan);
                        return(result);
                    }
                    return(result);
                }
            }

            return(VisitChildren(context));
        }
        public override object Visit(UnaryOperatorExpression unaryOperatorExpression, object data)
        {
            CodeExpression var;

            switch (unaryOperatorExpression.Op) {
                case UnaryOperatorType.Minus:
                    if (unaryOperatorExpression.Expression is PrimitiveExpression) {
                        PrimitiveExpression expression = (PrimitiveExpression)unaryOperatorExpression.Expression;
                        if (expression.Value is System.UInt32 || expression.Value is System.UInt16) {
                            return new CodePrimitiveExpression(Int32.Parse("-" + expression.StringValue));
                        }

                        if (expression.Value is int) {
                            return new CodePrimitiveExpression(- (int)expression.Value);
                        }
                        if (expression.Value is long) {
                            return new CodePrimitiveExpression(- (long)expression.Value);
                        }
                        if (expression.Value is double) {
                            return new CodePrimitiveExpression(- (double)expression.Value);
                        }
                        if (expression.Value is float) {
                            return new CodePrimitiveExpression(- (float)expression.Value);
                        }

                    }
                    return  new CodeBinaryOperatorExpression(new CodePrimitiveExpression(0),
                                                    CodeBinaryOperatorType.Subtract,
                                                    (CodeExpression)unaryOperatorExpression.Expression.AcceptVisitor(this, data));
                case UnaryOperatorType.Plus:
                    return unaryOperatorExpression.Expression.AcceptVisitor(this, data);

                case UnaryOperatorType.PostIncrement:
                    // emulate i++, with i = i + 1
                    var = (CodeExpression)unaryOperatorExpression.Expression.AcceptVisitor(this, data);

                    return new CodeAssignStatement(var,
                                    new CodeBinaryOperatorExpression(var,
                                                                     CodeBinaryOperatorType.Add,
                                                                     new CodePrimitiveExpression(1)));

                case UnaryOperatorType.PostDecrement:
                    // emulate i--, with i = i - 1
                    var = (CodeExpression)unaryOperatorExpression.Expression.AcceptVisitor(this, data);

                    return new CodeAssignStatement(var,
                        new CodeBinaryOperatorExpression(var,
                        CodeBinaryOperatorType.Subtract,
                        new CodePrimitiveExpression(1)));

                case UnaryOperatorType.Decrement:
                    // emulate --i, with i = i - 1
                    var = (CodeExpression)unaryOperatorExpression.Expression.AcceptVisitor(this, data);

                    return new CodeAssignStatement(var,
                        new CodeBinaryOperatorExpression(var,
                        CodeBinaryOperatorType.Subtract,
                        new CodePrimitiveExpression(1)));

                case UnaryOperatorType.Increment:
                    // emulate ++i, with i = i + 1
                    var = (CodeExpression)unaryOperatorExpression.Expression.AcceptVisitor(this, data);

                    return new CodeAssignStatement(var,
                        new CodeBinaryOperatorExpression(var,
                        CodeBinaryOperatorType.Add,
                        new CodePrimitiveExpression(1)));

            }
            return null;
        }
Exemple #22
0
        internal static Expression SubExpr(ScriptLoadingContext lcontext, bool isPrimary)
        {
            Expression e = null;

            Token T = lcontext.Lexer.Current;

            if (T.IsUnaryOperator())
            {
                lcontext.Lexer.Next();
                e = SubExpr(lcontext, false);

                // check for power operator -- it be damned forever and ever for being higher priority than unary ops
                Token unaryOp = T;
                T = lcontext.Lexer.Current;

                if (isPrimary && T.Type == TokenType.Op_Pwr)
                {
                    List <Expression> powerChain = new List <Expression>();
                    powerChain.Add(e);

                    while (isPrimary && T.Type == TokenType.Op_Pwr)
                    {
                        lcontext.Lexer.Next();
                        powerChain.Add(SubExpr(lcontext, false));
                        T = lcontext.Lexer.Current;
                    }

                    e = powerChain[powerChain.Count - 1];

                    for (int i = powerChain.Count - 2; i >= 0; i--)
                    {
                        e = BinaryOperatorExpression.CreatePowerExpression(powerChain[i], e, lcontext);
                    }
                }

                e = new UnaryOperatorExpression(lcontext, e, unaryOp);
            }
            else
            {
                e = SimpleExp(lcontext);
            }

            T = lcontext.Lexer.Current;

            if (isPrimary && T.IsBinaryOperator())
            {
                object chain = BinaryOperatorExpression.BeginOperatorChain();

                BinaryOperatorExpression.AddExpressionToChain(chain, e);

                while (T.IsBinaryOperator())
                {
                    BinaryOperatorExpression.AddOperatorToChain(chain, T);
                    lcontext.Lexer.Next();
                    Expression right = SubExpr(lcontext, false);
                    BinaryOperatorExpression.AddExpressionToChain(chain, right);
                    T = lcontext.Lexer.Current;
                }

                e = BinaryOperatorExpression.CommitOperatorChain(chain, lcontext);
            }

            return(e);
        }
Exemple #23
0
 public virtual object VisitUnaryOperatorExpression(UnaryOperatorExpression unaryOperatorExpression, object data)
 {
     throw new global::System.NotImplementedException("UnaryOperatorExpression");
 }
Exemple #24
0
        public override void VisitCastExpression(CastExpression castExpression)
        {
            // Even in readability mode, don't parenthesize casts of casts.
            if (!(castExpression.Expression is CastExpression))
            {
                ParenthesizeIfRequired(castExpression.Expression, InsertParenthesesForReadability ? PrecedenceLevel.NullableRewrap : PrecedenceLevel.Unary);
            }
            // There's a nasty issue in the C# grammar: cast expressions including certain operators are ambiguous in some cases
            // "(int)-1" is fine, but "(A)-b" is not a cast.
            UnaryOperatorExpression uoe = castExpression.Expression as UnaryOperatorExpression;

            if (uoe != null && !(uoe.Operator == UnaryOperatorType.BitNot || uoe.Operator == UnaryOperatorType.Not))
            {
                if (TypeCanBeMisinterpretedAsExpression(castExpression.Type))
                {
                    Parenthesize(castExpression.Expression);
                }
            }
            // The above issue can also happen with PrimitiveExpressions representing negative values:
            PrimitiveExpression pe = castExpression.Expression as PrimitiveExpression;

            if (pe != null && pe.Value != null && TypeCanBeMisinterpretedAsExpression(castExpression.Type))
            {
                TypeCode typeCode = Type.GetTypeCode(pe.Value.GetType());
                switch (typeCode)
                {
                case TypeCode.SByte:
                    if ((sbyte)pe.Value < 0)
                    {
                        Parenthesize(castExpression.Expression);
                    }
                    break;

                case TypeCode.Int16:
                    if ((short)pe.Value < 0)
                    {
                        Parenthesize(castExpression.Expression);
                    }
                    break;

                case TypeCode.Int32:
                    if ((int)pe.Value < 0)
                    {
                        Parenthesize(castExpression.Expression);
                    }
                    break;

                case TypeCode.Int64:
                    if ((long)pe.Value < 0)
                    {
                        Parenthesize(castExpression.Expression);
                    }
                    break;

                case TypeCode.Single:
                    if ((float)pe.Value < 0)
                    {
                        Parenthesize(castExpression.Expression);
                    }
                    break;

                case TypeCode.Double:
                    if ((double)pe.Value < 0)
                    {
                        Parenthesize(castExpression.Expression);
                    }
                    break;

                case TypeCode.Decimal:
                    if ((decimal)pe.Value < 0)
                    {
                        Parenthesize(castExpression.Expression);
                    }
                    break;
                }
            }
            base.VisitCastExpression(castExpression);
        }
Exemple #25
0
 public void VisitUnaryOperatorExpression(UnaryOperatorExpression unaryOperatorExpression)
 {
     throw new NotImplementedException();
 }
        /// <summary>
        /// Gets the row number in the C# 4.0 spec operator precedence table.
        /// </summary>
        static int GetPrecedence(Expression expr)
        {
            // Note: the operator precedence table on MSDN is incorrect
            if (expr is QueryExpression)
            {
                // Not part of the table in the C# spec, but we need to ensure that queries within
                // primary expressions get parenthesized.
                return(QueryOrLambda);
            }
            UnaryOperatorExpression uoe = expr as UnaryOperatorExpression;

            if (uoe != null)
            {
                if (uoe.Operator == UnaryOperatorType.PostDecrement || uoe.Operator == UnaryOperatorType.PostIncrement)
                {
                    return(Primary);
                }
                else
                {
                    return(Unary);
                }
            }
            if (expr is CastExpression)
            {
                return(Unary);
            }
            if (expr is PrimitiveExpression)
            {
                var value = ((PrimitiveExpression)expr).Value;
                if (value is int && (int)value < 0)
                {
                    return(Unary);
                }
                if (value is long && (long)value < 0)
                {
                    return(Unary);
                }
            }
            BinaryOperatorExpression boe = expr as BinaryOperatorExpression;

            if (boe != null)
            {
                switch (boe.Operator)
                {
                case BinaryOperatorType.Multiply:
                case BinaryOperatorType.Divide:
                case BinaryOperatorType.Modulus:
                    return(13);                            // multiplicative

                case BinaryOperatorType.Add:
                case BinaryOperatorType.Subtract:
                    return(12);                            // additive

                case BinaryOperatorType.ShiftLeft:
                case BinaryOperatorType.ShiftRight:
                    return(11);

                case BinaryOperatorType.GreaterThan:
                case BinaryOperatorType.GreaterThanOrEqual:
                case BinaryOperatorType.LessThan:
                case BinaryOperatorType.LessThanOrEqual:
                    return(RelationalAndTypeTesting);

                case BinaryOperatorType.Equality:
                case BinaryOperatorType.InEquality:
                    return(Equality);

                case BinaryOperatorType.BitwiseAnd:
                    return(8);

                case BinaryOperatorType.ExclusiveOr:
                    return(7);

                case BinaryOperatorType.BitwiseOr:
                    return(6);

                case BinaryOperatorType.ConditionalAnd:
                    return(5);

                case BinaryOperatorType.ConditionalOr:
                    return(4);

                case BinaryOperatorType.NullCoalescing:
                    return(3);

                default:
                    throw new NotSupportedException("Invalid value for BinaryOperatorType");
                }
            }
            if (expr is IsExpression || expr is AsExpression)
            {
                return(RelationalAndTypeTesting);
            }
            if (expr is ConditionalExpression)
            {
                return(Conditional);
            }
            if (expr is AssignmentExpression || expr is LambdaExpression)
            {
                return(Assignment);
            }
            // anything else: primary expression
            return(Primary);
        }
Exemple #27
0
 public virtual void Visit(UnaryOperatorExpression node)
 {
     VisitInternal(node.Operand);
 }
 public override void VisitUnaryOperatorExpression(UnaryOperatorExpression unaryOperatorExpression)
 {
     unaryOperatorExpression.Expression.AcceptVisitor(this);
 }
 public UnaryOperatorAction(ParseInfo parseInfo, Scope scope, UnaryOperatorExpression expression)
 {
     Value    = parseInfo.GetExpression(scope, expression.Value);
     Operator = expression.Operator;
 }
Exemple #30
0
        public override AstNode VisitUnaryOperatorExpression(UnaryOperatorExpression unaryOperatorExpression)
        {
            if (unaryOperatorExpression.Operator == UnaryOperatorType.Increment ||
                unaryOperatorExpression.Operator == UnaryOperatorType.PostIncrement ||
                unaryOperatorExpression.Operator == UnaryOperatorType.Decrement ||
                unaryOperatorExpression.Operator == UnaryOperatorType.PostDecrement)
            {
                var rr = this.Resolver.ResolveNode(unaryOperatorExpression, null);

                if (rr is ErrorResolveResult)
                {
                    UnaryOperatorExpression clonUnaryOperatorExpression = (UnaryOperatorExpression)base.VisitUnaryOperatorExpression(unaryOperatorExpression);
                    if (clonUnaryOperatorExpression == null)
                    {
                        clonUnaryOperatorExpression = (UnaryOperatorExpression)unaryOperatorExpression.Clone();
                    }

                    bool isPost = clonUnaryOperatorExpression.Operator == UnaryOperatorType.PostDecrement ||
                                  clonUnaryOperatorExpression.Operator == UnaryOperatorType.PostIncrement;

                    var isStatement = unaryOperatorExpression.Parent is ExpressionStatement;
                    var isIncr      = clonUnaryOperatorExpression.Operator == UnaryOperatorType.Increment || clonUnaryOperatorExpression.Operator == UnaryOperatorType.PostIncrement;
                    AssignmentExpression ae;

                    ae = new AssignmentExpression(clonUnaryOperatorExpression.Expression.Clone(), new BinaryOperatorExpression(clonUnaryOperatorExpression.Expression.Clone(), isIncr ? BinaryOperatorType.Add : BinaryOperatorType.Subtract, new PrimitiveExpression(1)));

                    if (isPost && !isStatement)
                    {
                        return(new InvocationExpression(new MemberReferenceExpression(new MemberReferenceExpression(new IdentifierExpression(CS.NS.ROOT), "Script"), "Identity"), clonUnaryOperatorExpression.Expression.Clone(), ae));
                    }
                    else
                    {
                        if (isStatement)
                        {
                            return(ae);
                        }

                        return(new ParenthesizedExpression(ae));
                    }
                }
                else
                {
                    var orr = (OperatorResolveResult)rr;

                    if (Helpers.IsFloatType(orr.Type, this.Resolver) || Helpers.Is64Type(orr.Type, this.Resolver))
                    {
                        return(base.VisitUnaryOperatorExpression(unaryOperatorExpression));
                    }

                    UnaryOperatorExpression clonUnaryOperatorExpression = (UnaryOperatorExpression)base.VisitUnaryOperatorExpression(unaryOperatorExpression);
                    if (clonUnaryOperatorExpression == null)
                    {
                        clonUnaryOperatorExpression = (UnaryOperatorExpression)unaryOperatorExpression.Clone();
                    }

                    bool isPost = clonUnaryOperatorExpression.Operator == UnaryOperatorType.PostDecrement ||
                                  clonUnaryOperatorExpression.Operator == UnaryOperatorType.PostIncrement;

                    var isStatement = unaryOperatorExpression.Parent is ExpressionStatement;
                    var isIncr      = clonUnaryOperatorExpression.Operator == UnaryOperatorType.Increment || clonUnaryOperatorExpression.Operator == UnaryOperatorType.PostIncrement;
                    AssignmentExpression ae;

                    if (orr.UserDefinedOperatorMethod != null)
                    {
                        ae = new AssignmentExpression(clonUnaryOperatorExpression.Expression.Clone(), clonUnaryOperatorExpression);
                    }
                    else
                    {
                        ae = new AssignmentExpression(clonUnaryOperatorExpression.Expression.Clone(),
                                                      new BinaryOperatorExpression(clonUnaryOperatorExpression.Expression.Clone(), isIncr ? BinaryOperatorType.Add : BinaryOperatorType.Subtract, new PrimitiveExpression(1)));
                    }

                    if (isPost && !isStatement)
                    {
                        return(new InvocationExpression(new MemberReferenceExpression(new MemberReferenceExpression(new IdentifierExpression(CS.NS.ROOT), "Script"), "Identity"), clonUnaryOperatorExpression.Expression.Clone(), ae));
                    }
                    else
                    {
                        if (isStatement)
                        {
                            return(ae);
                        }

                        return(new ParenthesizedExpression(ae));
                    }
                }
            }

            return(base.VisitUnaryOperatorExpression(unaryOperatorExpression));
        }
Exemple #31
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);
        }
Exemple #32
0
 public string _Visit(UnaryOperatorType op)
 {
     return(UnaryOperatorExpression.GetOperatorRole(op).Token);
 }
Exemple #33
0
		bool IsUnaryModifierExpression(UnaryOperatorExpression expr)
		{
			return expr.Operator == UnaryOperatorType.Increment || expr.Operator == UnaryOperatorType.PostIncrement || expr.Operator == UnaryOperatorType.Decrement || expr.Operator == UnaryOperatorType.PostDecrement;
		}
Exemple #34
0
 public override void VisitUnaryOperatorExpression(UnaryOperatorExpression unaryOperatorExpression)
 {
     new UnaryOperatorBlock(this, unaryOperatorExpression).Emit();
 }
Exemple #35
0
 public override object VisitUnaryOperatorExpression(UnaryOperatorExpression unaryOperatorExpression, object data)
 {
     return(base.VisitUnaryOperatorExpression(unaryOperatorExpression, data));
 }
Exemple #36
0
        public override object VisitUnaryOperatorExpression(UnaryOperatorExpression unaryOperatorExpression, object data)
        {
            CodeExpression var;

            switch (unaryOperatorExpression.Op)
            {
            case UnaryOperatorType.Minus:
                if (unaryOperatorExpression.Expression is PrimitiveExpression)
                {
                    PrimitiveExpression expression = (PrimitiveExpression)unaryOperatorExpression.Expression;
                    if (expression.Value is int)
                    {
                        return(new CodePrimitiveExpression(-(int)expression.Value));
                    }
                    if (expression.Value is System.UInt32 || expression.Value is System.UInt16)
                    {
                        return(new CodePrimitiveExpression(Int32.Parse("-" + expression.StringValue)));
                    }

                    if (expression.Value is long)
                    {
                        return(new CodePrimitiveExpression(-(long)expression.Value));
                    }
                    if (expression.Value is double)
                    {
                        return(new CodePrimitiveExpression(-(double)expression.Value));
                    }
                    if (expression.Value is float)
                    {
                        return(new CodePrimitiveExpression(-(float)expression.Value));
                    }
                }
                return(new CodeBinaryOperatorExpression(new CodePrimitiveExpression(0),
                                                        CodeBinaryOperatorType.Subtract,
                                                        (CodeExpression)unaryOperatorExpression.Expression.AcceptVisitor(this, data)));

            case UnaryOperatorType.Plus:
                return(unaryOperatorExpression.Expression.AcceptVisitor(this, data));

            case UnaryOperatorType.PostIncrement:
                // emulate i++, with i = i + 1
                var = (CodeExpression)unaryOperatorExpression.Expression.AcceptVisitor(this, data);

                return(new CodeAssignStatement(var,
                                               new CodeBinaryOperatorExpression(var,
                                                                                CodeBinaryOperatorType.Add,
                                                                                new CodePrimitiveExpression(1))));

            case UnaryOperatorType.PostDecrement:
                // emulate i--, with i = i - 1
                var = (CodeExpression)unaryOperatorExpression.Expression.AcceptVisitor(this, data);

                return(new CodeAssignStatement(var,
                                               new CodeBinaryOperatorExpression(var,
                                                                                CodeBinaryOperatorType.Subtract,
                                                                                new CodePrimitiveExpression(1))));

            case UnaryOperatorType.Decrement:
                // emulate --i, with i = i - 1
                var = (CodeExpression)unaryOperatorExpression.Expression.AcceptVisitor(this, data);

                return(new CodeAssignStatement(var,
                                               new CodeBinaryOperatorExpression(var,
                                                                                CodeBinaryOperatorType.Subtract,
                                                                                new CodePrimitiveExpression(1))));

            case UnaryOperatorType.Increment:
                // emulate ++i, with i = i + 1
                var = (CodeExpression)unaryOperatorExpression.Expression.AcceptVisitor(this, data);

                return(new CodeAssignStatement(var,
                                               new CodeBinaryOperatorExpression(var,
                                                                                CodeBinaryOperatorType.Add,
                                                                                new CodePrimitiveExpression(1))));
            }
            return(null);
        }
Exemple #37
0
 public override AstNode VisitUnaryOperatorExpression(UnaryOperatorExpression unaryOperatorExpression, ILGenerator data)
 {
     return(_constructorEmitter.EmitUnaryOperatorExpression(unaryOperatorExpression, data));
 }
Exemple #38
0
 private AphidRuntimeException CreateUnaryOperatorException(UnaryOperatorExpression expression)
 {
     return(new AphidRuntimeException("Unknown operator {0} in expression {1}.", expression.Operator, expression));
 }
 public override void VisitUnaryOperatorExpression(UnaryOperatorExpression unaryOperatorExpression)
 {
     HandleExpressionNode(unaryOperatorExpression);
 }
Exemple #40
0
        private AphidObject InterpretUnaryOperatorExpression(UnaryOperatorExpression expression)
        {
            if (!expression.IsPostfix)
            {
                switch (expression.Operator)
                {
                case AphidTokenType.retKeyword:
                    SetReturnValue(ValueHelper.Wrap(InterpretExpression(expression.Operand)));
                    _isReturning = true;
                    return(null);

                case AphidTokenType.deleteKeyword:
                    var operand = ((IdentifierExpression)expression.Operand).Identifier;
                    return(new AphidObject(_currentScope.TryResolveAndRemove(operand)));

                case AphidTokenType.NotOperator:
                    return(new AphidObject(!(bool)ValueHelper.Unwrap(InterpretExpression(expression.Operand) as AphidObject)));

                case AphidTokenType.IncrementOperator:
                    var obj = InterpretExpression(expression.Operand) as AphidObject;
                    obj.Value = ((decimal)obj.Value) + 1;
                    return(obj);

                case AphidTokenType.DecrementOperator:
                    obj       = InterpretExpression(expression.Operand) as AphidObject;
                    obj.Value = ((decimal)obj.Value) - 1;
                    return(obj);

                case AphidTokenType.DistinctOperator:
                    obj = ((AphidObject)InterpretExpression(expression.Operand));
                    var list = obj.Value as List <AphidObject>;

                    if (list == null)
                    {
                        throw CreateUnaryOperatorException(expression);
                    }

                    return(new AphidObject(list.Distinct(_comparer).ToList()));

                default:
                    throw CreateUnaryOperatorException(expression);
                }
            }
            else
            {
                switch (expression.Operator)
                {
                case AphidTokenType.IncrementOperator:
                    var obj = InterpretExpression(expression.Operand) as AphidObject;
                    var v   = obj.Value;
                    obj.Value = ((decimal)obj.Value) + 1;
                    return(new AphidObject(v));

                case AphidTokenType.DecrementOperator:
                    obj       = InterpretExpression(expression.Operand) as AphidObject;
                    v         = obj.Value;
                    obj.Value = ((decimal)obj.Value) - 1;
                    return(new AphidObject(v));

                case AphidTokenType.definedKeyword:
                    if (expression.Operand is IdentifierExpression)
                    {
                        return(ValueHelper.Wrap(InterpretIdentifierExpression(expression.Operand as IdentifierExpression) != null));
                    }
                    else if (expression.Operand is BinaryOperatorExpression)
                    {
                        var objRef = InterpretBinaryOperatorExpression(expression.Operand as BinaryOperatorExpression, true) as AphidRef;
                        return(new AphidObject(objRef.Object.ContainsKey(objRef.Name)));
                    }
                    else
                    {
                        throw new AphidRuntimeException("Unknown ? operand");
                    }


                //var obj = InterpretExpression(

                default:
                    throw CreateUnaryOperatorException(expression);
                }
            }
        }
Exemple #41
0
        public override StringBuilder VisitUnaryOperatorExpression(UnaryOperatorExpression unaryOperatorExpression, int data)
        {
            var result = new StringBuilder();

            var exp = unaryOperatorExpression.Expression.AcceptVisitor(this, data);

            switch (unaryOperatorExpression.Operator)
            {
                case UnaryOperatorType.Decrement:
                    return result.Append("--").Append(exp);
                case UnaryOperatorType.Increment:
                    return result.Append("++").Append(exp);
                case UnaryOperatorType.Minus:
                    return result.Append("-").Append(exp);
                case UnaryOperatorType.Plus:
                    return result.Append("+").Append(exp);
                case UnaryOperatorType.BitNot:
                    return result.Append("~").Append(exp);
                case UnaryOperatorType.Not:
                    return result.Append("!").Append(exp);
                case UnaryOperatorType.PostDecrement:
                    return result.Append(exp).Append("--");
                case UnaryOperatorType.PostIncrement:
                    return result.Append(exp).Append("++");
            }

            throw new NotImplementedException();
        }
Exemple #42
0
        public UstNode VisitExpression(JavaParser.ExpressionContext context)
        {
            var        textSpan       = context.GetTextSpan();
            var        child0Terminal = context.GetChild(0) as ITerminalNode;
            Expression target;
            Expression result;

            if (child0Terminal != null)
            {
                switch (child0Terminal.Symbol.Type)
                {
                case JavaParser.NEW:
                    result = (Expression)Visit(context.creator());
                    return(result);

                case JavaParser.LPAREN:     // '(' type ')' expression
                    var type = (TypeToken)Visit(context.typeType());
                    target = (Expression)Visit(context.expression(0));
                    result = new CastExpression(type, target, textSpan, FileNode);
                    return(result);

                default:     // unary operator ('+', '-', '++', '--', '~', '!')
                    UnaryOperator op        = UnaryOperatorLiteral.PrefixTextUnaryOperator[child0Terminal.GetText()];
                    var           opLiteral = new UnaryOperatorLiteral(op, child0Terminal.GetTextSpan(), FileNode);
                    target = (Expression)Visit(context.expression(0));
                    result = new UnaryOperatorExpression(opLiteral, target, textSpan, FileNode);
                    return(result);
                }
            }

            ArgsNode args;
            var      child1Terminal = context.GetChild(1) as ITerminalNode;

            if (child1Terminal != null)
            {
                switch (child1Terminal.Symbol.Type)
                {
                case JavaParser.DOT:     // '.'
                    target = (Expression)Visit(context.expression(0));
                    var id = context.IDENTIFIER();
                    if (id != null)
                    {
                        result = new MemberReferenceExpression(target, (IdToken)Visit(id), textSpan, FileNode);
                        return(result);
                    }

                    var explicitGenericInvocation = context.explicitGenericInvocation();
                    if (explicitGenericInvocation != null)
                    {
                        return(VisitChildren(context).ToExpressionIfRequired());
                    }

                    var child2Terminal = context.GetChild <ITerminalNode>(1);
                    // TODO: implement
                    switch (child2Terminal.Symbol.Type)
                    {
                    case JavaParser.THIS:
                        break;

                    case JavaParser.NEW:
                        break;

                    case JavaParser.SUPER:
                        break;
                    }
                    break;

                case JavaParser.LBRACK:     // '['
                    target = (Expression)Visit(context.expression(0));
                    Expression expr = (Expression)Visit(context.expression(1));
                    args = new ArgsNode(new Expression[] { expr }, expr.TextSpan, FileNode);

                    result = new IndexerExpression(target, args, textSpan, FileNode);
                    return(result);

                case JavaParser.LPAREN:     // '('
                    target = (Expression)Visit(context.expression(0));
                    // TODO: fix with ArgsNode
                    JavaParser.ExpressionListContext expressionList = context.expressionList();

                    if (expressionList != null)
                    {
                        args = (ArgsNode)Visit(expressionList);
                    }
                    else
                    {
                        args = new ArgsNode();
                    }

                    result = new InvocationExpression(target, args, textSpan, FileNode);
                    return(result);

                case JavaParser.INSTANCEOF:     // x instanceof y -> (y)x != null
                    var expression = (Expression)Visit(context.expression(0));
                    var type       = (TypeToken)Visit(context.typeType());
                    result = new BinaryOperatorExpression
                    {
                        Left     = new CastExpression(type, expression, context.GetTextSpan(), FileNode),
                        Operator = new BinaryOperatorLiteral(BinaryOperator.NotEqual, default(TextSpan), FileNode),
                        Right    = new NullLiteral(default(TextSpan), FileNode),
                        TextSpan = context.GetTextSpan(),
                        FileNode = FileNode
                    };
                    return(result);

                case JavaParser.QUESTION:     // '?'
                    var condition = (Expression)Visit(context.expression(0));
                    var trueExpr  = (Expression)Visit(context.expression(1));
                    var falseExpr = (Expression)Visit(context.expression(2));

                    result = new ConditionalExpression(condition, trueExpr, falseExpr, textSpan, FileNode);
                    return(result);

                default:     // binary operator
                    string text = child1Terminal.GetText();
                    var    left = (Expression)Visit(context.expression(0));
                    JavaParser.ExpressionContext expr1 = context.expression(1);

                    if (expr1 != null)
                    {
                        var right = (Expression)Visit(expr1);

                        if (text == "=")
                        {
                            result = new AssignmentExpression(left, right, textSpan, FileNode);
                        }
                        else if (BinaryOperatorLiteral.TextBinaryAssignmentOperator.Contains(text))
                        {
                            BinaryOperator op;
                            if (text == ">>>=")
                            {
                                op = BinaryOperator.ShiftRight;     // TODO: fix shift operator.
                            }
                            else
                            {
                                op = BinaryOperatorLiteral.TextBinaryOperator[text.Remove(text.Length - 1)];
                            }

                            result = ConverterHelper.ConvertToAssignmentExpression(left, op, child1Terminal.GetTextSpan(), right,
                                                                                   context.GetTextSpan(), FileNode);
                        }
                        else
                        {
                            BinaryOperator op;
                            if (text == ">>>")
                            {
                                op = BinaryOperator.ShiftRight;      // TODO: fix shift operator.
                            }
                            else
                            {
                                op = BinaryOperatorLiteral.TextBinaryOperator[text];
                            }
                            var opLiteral = new BinaryOperatorLiteral(op, child1Terminal.GetTextSpan(), FileNode);

                            result = new BinaryOperatorExpression(left, opLiteral, right, textSpan, FileNode);
                        }
                    }
                    else
                    {
                        // post increment or decrement.
                        UnaryOperator op        = UnaryOperatorLiteral.PostfixTextUnaryOperator[text];
                        var           opLiteral = new UnaryOperatorLiteral(op, child1Terminal.GetTextSpan(), FileNode);

                        result = new UnaryOperatorExpression(opLiteral, left, textSpan, FileNode);
                        return(result);
                    }

                    return(result);
                }
            }

            return(Visit(context.GetChild(0)));
        }
Exemple #43
0
        public override AstNode VisitUnaryOperatorExpression(UnaryOperatorExpression unaryOperatorExpression)
        {
            if (this.Rules.Integer == IntegerRule.Managed && (unaryOperatorExpression.Operator == UnaryOperatorType.Increment ||
                                                              unaryOperatorExpression.Operator == UnaryOperatorType.PostIncrement ||
                                                              unaryOperatorExpression.Operator == UnaryOperatorType.Decrement ||
                                                              unaryOperatorExpression.Operator == UnaryOperatorType.PostDecrement))
            {
                var rr            = this.Resolver.ResolveNode(unaryOperatorExpression, null);
                var expression_rr = this.Resolver.ResolveNode(unaryOperatorExpression.Expression, null);

                if (rr is ErrorResolveResult)
                {
                    UnaryOperatorExpression clonUnaryOperatorExpression = (UnaryOperatorExpression)base.VisitUnaryOperatorExpression(unaryOperatorExpression);
                    if (clonUnaryOperatorExpression == null)
                    {
                        clonUnaryOperatorExpression = (UnaryOperatorExpression)unaryOperatorExpression.Clone();
                    }

                    bool isPost = clonUnaryOperatorExpression.Operator == UnaryOperatorType.PostDecrement ||
                                  clonUnaryOperatorExpression.Operator == UnaryOperatorType.PostIncrement;

                    var isStatement = unaryOperatorExpression.Parent is ExpressionStatement;
                    var isIncr      = clonUnaryOperatorExpression.Operator == UnaryOperatorType.Increment || clonUnaryOperatorExpression.Operator == UnaryOperatorType.PostIncrement;
                    AssignmentExpression ae;

                    ae = new AssignmentExpression(clonUnaryOperatorExpression.Expression.Clone(), new BinaryOperatorExpression(clonUnaryOperatorExpression.Expression.Clone(), isIncr ? BinaryOperatorType.Add : BinaryOperatorType.Subtract, new PrimitiveExpression(1)));

                    if (isPost && !isStatement)
                    {
                        return(new InvocationExpression(new MemberReferenceExpression(new MemberReferenceExpression(new TypeReferenceExpression(new MemberType(new SimpleType("global"), CS.NS.BRIDGE)
                        {
                            IsDoubleColon = true
                        }), "Script"), "Identity"), clonUnaryOperatorExpression.Expression.Clone(), ae));
                    }
                    else
                    {
                        if (isStatement)
                        {
                            return(ae);
                        }

                        return(new ParenthesizedExpression(ae));
                    }
                }
                else
                {
                    var orr = (OperatorResolveResult)rr;

                    if (Helpers.IsFloatType(orr.Type, this.Resolver) || Helpers.Is64Type(orr.Type, this.Resolver))
                    {
                        return(base.VisitUnaryOperatorExpression(unaryOperatorExpression));
                    }

                    UnaryOperatorExpression clonUnaryOperatorExpression = (UnaryOperatorExpression)base.VisitUnaryOperatorExpression(unaryOperatorExpression);
                    if (clonUnaryOperatorExpression == null)
                    {
                        clonUnaryOperatorExpression = (UnaryOperatorExpression)unaryOperatorExpression.Clone();
                    }

                    bool isPost = clonUnaryOperatorExpression.Operator == UnaryOperatorType.PostDecrement ||
                                  clonUnaryOperatorExpression.Operator == UnaryOperatorType.PostIncrement;

                    var isStatement        = unaryOperatorExpression.Parent is ExpressionStatement;
                    var isIncr             = clonUnaryOperatorExpression.Operator == UnaryOperatorType.Increment || clonUnaryOperatorExpression.Operator == UnaryOperatorType.PostIncrement;
                    var needReturnOriginal = isPost && !isStatement;

                    Expression expression      = clonUnaryOperatorExpression.Expression.Clone();
                    Expression expressionAfter = clonUnaryOperatorExpression.Expression.Clone();

                    AssignmentExpression ae = null;

                    if (orr.UserDefinedOperatorMethod != null)
                    {
                        ae = new AssignmentExpression(expressionAfter.Clone(), clonUnaryOperatorExpression);
                    }
                    else if (clonUnaryOperatorExpression.Expression is MemberReferenceExpression mre && expression_rr is MemberResolveResult member_rr)
                    {
                        if (needReturnOriginal)
                        {
                            bool isSimple = (member_rr != null &&
                                             (member_rr.TargetResult is ThisResolveResult ||
                                              member_rr.TargetResult is LocalResolveResult ||
                                              member_rr.TargetResult is TypeResolveResult ||
                                              member_rr.TargetResult is ConstantResolveResult));

                            expression = isSimple ? mre.Clone() : new MemberReferenceExpression(new InvocationExpression(new MemberReferenceExpression(new MemberReferenceExpression(new TypeReferenceExpression(new MemberType(new SimpleType("global"), CS.NS.BRIDGE)
                            {
                                IsDoubleColon = true
                            }), "Script"), "ToTemp"), new PrimitiveExpression("idx" + tempKey), mre.Target.Clone()), mre.MemberName);
                            expressionAfter = new InvocationExpression(new MemberReferenceExpression(new MemberReferenceExpression(new TypeReferenceExpression(new MemberType(new SimpleType("global"), CS.NS.BRIDGE)
                            {
                                IsDoubleColon = true
                            }), "Script"), "FromTemp"), new PrimitiveExpression("idx" + tempKey++), mre.Target.Clone());
                        }
                        else
                        {
                            expressionAfter = null;
                        }

                        ae = BuildMemberReferenceReplacement(isIncr ? BinaryOperatorType.Add : BinaryOperatorType.Subtract, mre, member_rr, expressionAfter);
                    }
                    else if (clonUnaryOperatorExpression.Expression is IndexerExpression ie && expression_rr is ArrayAccessResolveResult array_rr)
                    {
                        IndexerExpression cacheIndexer = null;
                        if (needReturnOriginal)
                        {
                            var  array_target_rr = array_rr.Array as MemberResolveResult;
                            bool isSimpleTarget  = (array_target_rr != null && array_target_rr.Member is IField &&
                                                    (array_target_rr.TargetResult is ThisResolveResult ||
                                                     array_target_rr.TargetResult is LocalResolveResult ||
                                                     array_target_rr.TargetResult is TypeResolveResult ||
                                                     array_target_rr.TargetResult is ConstantResolveResult)) ||
                                                   (array_rr.Array is ThisResolveResult ||
                                                    array_rr.Array is LocalResolveResult ||
                                                    array_rr.Array is ConstantResolveResult);

                            bool simpleIndex = true;

                            foreach (var index in array_rr.Indexes)
                            {
                                var  indexMemberTargetrr = index as MemberResolveResult;
                                bool isIndexSimple       = (indexMemberTargetrr != null && indexMemberTargetrr.Member is IField &&
                                                            (indexMemberTargetrr.TargetResult is ThisResolveResult ||
                                                             indexMemberTargetrr.TargetResult is LocalResolveResult)) || index is ThisResolveResult || index is LocalResolveResult || index is ConstantResolveResult;

                                if (!isIndexSimple)
                                {
                                    simpleIndex = false;
                                    break;
                                }
                            }
                            var leftIndexerArgs  = new List <Expression>();
                            var rightIndexerArgs = new List <Expression>();

                            foreach (var index in ie.Arguments)
                            {
                                var expr = simpleIndex ? index.Clone() : new InvocationExpression(new MemberReferenceExpression(new MemberReferenceExpression(new TypeReferenceExpression(new MemberType(new SimpleType("global"), CS.NS.BRIDGE)
                                {
                                    IsDoubleColon = true
                                }), "Script"), "ToTemp"), new PrimitiveExpression("idx" + tempKey), index.Clone());
                                leftIndexerArgs.Add(expr);

                                expr = simpleIndex ? index.Clone() : new InvocationExpression(new MemberReferenceExpression(new MemberReferenceExpression(new TypeReferenceExpression(new MemberType(new SimpleType("global"), CS.NS.BRIDGE)
                                {
                                    IsDoubleColon = true
                                }), "Script"), "FromTemp"), new PrimitiveExpression("idx" + tempKey++), index.Clone());
                                rightIndexerArgs.Add(expr);
                            }

                            var leftExpr = new InvocationExpression(new MemberReferenceExpression(new MemberReferenceExpression(new TypeReferenceExpression(new MemberType(new SimpleType("global"), CS.NS.BRIDGE)
                            {
                                IsDoubleColon = true
                            }), "Script"), "ToTemp"), new PrimitiveExpression("idx" + tempKey), ie.Target.Clone());
                            var rightExpr = new InvocationExpression(new MemberReferenceExpression(new MemberReferenceExpression(new TypeReferenceExpression(new MemberType(new SimpleType("global"), CS.NS.BRIDGE)
                            {
                                IsDoubleColon = true
                            }), "Script"), "FromTemp"), new PrimitiveExpression("idx" + tempKey++), ie.Target.Clone());

                            var leftIndexer  = new IndexerExpression(isSimpleTarget ? ie.Target.Clone() : leftExpr, leftIndexerArgs);
                            var rightIndexer = new IndexerExpression(isSimpleTarget ? ie.Target.Clone() : rightExpr, rightIndexerArgs);

                            expression   = leftIndexer;
                            cacheIndexer = rightIndexer;
                        }

                        ae = BuildIndexerReplacement(isStatement, isIncr ? BinaryOperatorType.Add : BinaryOperatorType.Subtract, ie, array_rr, cacheIndexer);
                    }
Exemple #44
0
			public override object Visit(Await awaitExpr)
			{
				var result = new UnaryOperatorExpression();
				result.Operator = UnaryOperatorType.Await;
				result.AddChild(new CSharpTokenNode(Convert(awaitExpr.Location), UnaryOperatorExpression.AwaitRole), UnaryOperatorExpression.AwaitRole);
				if (awaitExpr.Expression != null)
					result.AddChild((Expression)awaitExpr.Expression.Accept(this), Roles.Expression);
				return result;
			}
Exemple #45
0
        public ArgumentsInfo(IEmitter emitter, UnaryOperatorExpression unaryOperatorExpression, OperatorResolveResult operatorResolveResult, IMethod method)
        {
            this.Emitter = emitter;
            this.Expression = unaryOperatorExpression;
            this.OperatorResolveResult = operatorResolveResult;

            this.BuildOperatorArgumentsList(new Expression[] { unaryOperatorExpression.Expression }, operatorResolveResult.UserDefinedOperatorMethod ?? method);
            this.BuildOperatorTypedArguments();
        }
Exemple #46
0
			public override object Visit (Unary unaryExpression)
			{
				var result = new UnaryOperatorExpression ();
				switch (unaryExpression.Oper) {
				case Unary.Operator.UnaryPlus:
					result.UnaryOperatorType = UnaryOperatorType.Plus;
					break;
				case Unary.Operator.UnaryNegation:
					result.UnaryOperatorType = UnaryOperatorType.Minus;
					break;
				case Unary.Operator.LogicalNot:
					result.UnaryOperatorType = UnaryOperatorType.Not;
					break;
				case Unary.Operator.OnesComplement:
					result.UnaryOperatorType = UnaryOperatorType.BitNot;
					break;
				case Unary.Operator.AddressOf:
					result.UnaryOperatorType = UnaryOperatorType.AddressOf;
					break;
				}
				result.AddChild (new CSharpTokenNode (Convert (unaryExpression.Location), 1), UnaryOperatorExpression.Operator);
				result.AddChild ((INode)unaryExpression.Expr.Accept (this), UnaryOperatorExpression.Roles.Expression);
				return result;
			}
        Expression ConvertUnaryOperator(InvocationExpression invocation, UnaryOperatorType op, bool? isChecked = null)
        {
            if (invocation.Arguments.Count < 1)
                return NotSupported(invocation);

            Expression expr = Convert(invocation.Arguments.ElementAt(0));
            if (expr == null)
                return null;

            UnaryOperatorExpression uoe = new UnaryOperatorExpression(op, expr);
            if (isChecked != null)
                uoe.AddAnnotation(isChecked.Value ? AddCheckedBlocks.CheckedAnnotation : AddCheckedBlocks.UncheckedAnnotation);

            switch (invocation.Arguments.Count) {
                case 1:
                    return uoe;
                case 2:
                    Match m = getMethodFromHandlePattern.Match(invocation.Arguments.ElementAt(1));
                    if (m.Success)
                        return uoe.WithAnnotation(m.Get<AstNode>("method").Single().Annotation<MethodReference>());
                    else
                        return null;
                default:
                    return NotSupported(invocation);
            }
        }
Exemple #48
0
			public override object Visit (Indirection indirectionExpression)
			{
				var result = new UnaryOperatorExpression ();
				result.UnaryOperatorType = UnaryOperatorType.Dereference;
				var location = LocationsBag.GetLocations (indirectionExpression);
				if (location != null)
					result.AddChild (new CSharpTokenNode (Convert (location[0]), 2), UnaryOperatorExpression.Operator);
				result.AddChild ((INode)indirectionExpression.Expr.Accept (this), UnaryOperatorExpression.Roles.Expression);
				return result;
			}
Exemple #49
0
			public override object Visit(Indirection indirectionExpression)
			{
				var result = new UnaryOperatorExpression();
				result.Operator = UnaryOperatorType.Dereference;
				result.AddChild(new CSharpTokenNode(Convert(indirectionExpression.Location), UnaryOperatorExpression.DereferenceRole), UnaryOperatorExpression.DereferenceRole);
				if (indirectionExpression.Expr != null)
					result.AddChild((Expression)indirectionExpression.Expr.Accept(this), Roles.Expression);
				return result;
			}
Exemple #50
0
 public virtual T Visit(UnaryOperatorExpression unaryOperatorExpression)
 {
     return(VisitChildren(unaryOperatorExpression));
 }
		public virtual void VisitUnaryOperatorExpression (UnaryOperatorExpression unaryOperatorExpression)
		{
			VisitChildren (unaryOperatorExpression);
		}
Exemple #52
0
 public UnaryOperatorBlock(IEmitter emitter, UnaryOperatorExpression unaryOperatorExpression)
     : base(emitter, unaryOperatorExpression)
 {
     this.Emitter = emitter;
     this.UnaryOperatorExpression = unaryOperatorExpression;
 }
Exemple #53
0
			public override object Visit (UnaryMutator unaryMutatorExpression)
			{
				var result = new UnaryOperatorExpression ();
				
				INode expression = (INode)unaryMutatorExpression.Expr.Accept (this);
				switch (unaryMutatorExpression.UnaryMutatorMode) {
				case UnaryMutator.Mode.PostDecrement:
					result.UnaryOperatorType = UnaryOperatorType.PostDecrement;
					result.AddChild (expression, UnaryOperatorExpression.Roles.Expression);
					result.AddChild (new CSharpTokenNode (Convert (unaryMutatorExpression.Location), 2), UnaryOperatorExpression.Operator);
					break;
				case UnaryMutator.Mode.PostIncrement:
					result.UnaryOperatorType = UnaryOperatorType.PostIncrement;
					result.AddChild (expression, UnaryOperatorExpression.Roles.Expression);
					result.AddChild (new CSharpTokenNode (Convert (unaryMutatorExpression.Location), 2), UnaryOperatorExpression.Operator);
					break;
					
				case UnaryMutator.Mode.PreIncrement:
					result.UnaryOperatorType = UnaryOperatorType.Increment;
					result.AddChild (new CSharpTokenNode (Convert (unaryMutatorExpression.Location), 2), UnaryOperatorExpression.Operator);
					result.AddChild (expression, UnaryOperatorExpression.Roles.Expression);
					break;
				case UnaryMutator.Mode.PreDecrement:
					result.UnaryOperatorType = UnaryOperatorType.Decrement;
					result.AddChild (new CSharpTokenNode (Convert (unaryMutatorExpression.Location), 2), UnaryOperatorExpression.Operator);
					result.AddChild (expression, UnaryOperatorExpression.Roles.Expression);
					break;
				}
				
				return result;
			}
 public virtual object Visit(UnaryOperatorExpression unaryOperatorExpression, object data)
 {
     Debug.Assert(unaryOperatorExpression != null);
     Debug.Assert(unaryOperatorExpression.Expression != null);
     return(unaryOperatorExpression.Expression.AcceptVisitor(this, data));
 }
Exemple #55
0
		public void VisitUnaryOperatorExpression(UnaryOperatorExpression unaryOperatorExpression)
		{
			StartNode(unaryOperatorExpression);
			UnaryOperatorType opType = unaryOperatorExpression.Operator;
			var opSymbol = UnaryOperatorExpression.GetOperatorRole(opType);
			if (opType == UnaryOperatorType.Await) {
				WriteKeyword(opSymbol);
			} else if (!(opType == UnaryOperatorType.PostIncrement || opType == UnaryOperatorType.PostDecrement)) {
				WriteToken(opSymbol);
			}
			unaryOperatorExpression.Expression.AcceptVisitor(this);
			if (opType == UnaryOperatorType.PostIncrement || opType == UnaryOperatorType.PostDecrement) {
				WriteToken(opSymbol);
			}
			EndNode(unaryOperatorExpression);
		}
 public JNode VisitUnaryOperatorExpression(UnaryOperatorExpression node)
 {
     return(Visit(node.Resolve()));
     //return new JsPreUnaryExpression { Operator = _Visit(node.Operator), Right = VisitExpression(node.Expression) };
 }
Exemple #57
0
		bool ExtractExpression (Statement statement, out Expression leftSide, out Expression rightSide) {
			ExpressionStatement expression = statement as ExpressionStatement;
			if (expression != null) {
				AssignmentExpression assignment = expression.Expression as AssignmentExpression;
				if (assignment != null) {
					if (assignment.Operator == AssignmentOperatorType.Add) {
						leftSide = assignment.Left;
						rightSide = assignment.Right;
						return true;
					}
					if (assignment.Operator == AssignmentOperatorType.Subtract) {
						leftSide = assignment.Left;
						rightSide = new UnaryOperatorExpression(UnaryOperatorType.Minus, assignment.Right.Clone());
						return true;
					}

					leftSide = null;
					rightSide = null;
					return false;
				}

				UnaryOperatorExpression unary = expression.Expression as UnaryOperatorExpression;
				if (unary != null) {
					leftSide = unary.Expression;
					if (unary.Operator == UnaryOperatorType.Increment || unary.Operator == UnaryOperatorType.PostIncrement) {
						rightSide = new PrimitiveExpression(1);
						return true;
					} else if (unary.Operator == UnaryOperatorType.Decrement || unary.Operator == UnaryOperatorType.PostDecrement) {
						rightSide = new PrimitiveExpression(-1);
						return true;
					} else {
						leftSide = null;
						rightSide = null;
						return false;
					}
				}
			}

			if (statement is EmptyStatement || statement.IsNull) {
				leftSide = null;
				rightSide = null;
				return true;
			}

			BlockStatement block = statement as BlockStatement;
			if (block != null) {
				leftSide = null;
				rightSide = null;

				foreach (Statement child in block.Statements) {
					Expression newLeft, newRight;
					if (!ExtractExpression(child, out newLeft, out newRight)) {
						leftSide = null;
						rightSide = null;
						return false;
					}

					if (newLeft == null) {
						continue;
					}

					if (leftSide == null) {
						leftSide = newLeft;
						rightSide = newRight;
					} else if (SameNode(leftSide, newLeft)) {
						rightSide = new BinaryOperatorExpression(ParenthesizeIfNeeded(rightSide).Clone(),
						                                         BinaryOperatorType.Add,
						                                         ParenthesizeIfNeeded(newRight).Clone());
					} else {
						return false;
					}
				}

				return true;
			}

			IfElseStatement condition = statement as IfElseStatement;
			if (condition != null) {
				Expression ifLeft, ifRight;
				if (!ExtractExpression(condition.TrueStatement, out ifLeft, out ifRight)) {
					leftSide = null;
					rightSide = null;
					return false;
				}

				Expression elseLeft, elseRight;
				if (!ExtractExpression(condition.FalseStatement, out elseLeft, out elseRight)) {
					leftSide = null;
					rightSide = null;
					return false;
				}

				if (ifLeft == null && elseLeft == null) {
					leftSide = null;
					rightSide = null;
					return true;
				}

				if (ifLeft != null && elseLeft != null && !SameNode(ifLeft, elseLeft)) {
					leftSide = null;
					rightSide = null;
					return false;
				}

				ifRight = ifRight ?? new PrimitiveExpression(0);
				elseRight = elseRight ?? new PrimitiveExpression(0);

				leftSide = ifLeft ?? elseLeft;
				rightSide = new ConditionalExpression(condition.Condition.Clone(), ifRight.Clone(), elseRight.Clone());
				return true;
			}

			leftSide = null;
			rightSide = null;
			return false;
		}
            void TransformBody(List <InvocationExpression> validInvocations, bool isVoid, bool isParameterizedTask, InvocationExpression returnedContinuation, string taskCompletionSourceIdentifier, BlockStatement blockStatement)
            {
                if (!isVoid)
                {
                    if (returnedContinuation == null)
                    {
                        //Is TaskCompletionSource-based
                        blockStatement.Statements.First().Remove(); //Remove task completion source declaration
                        blockStatement.Statements.Last().Remove();  //Remove final return
                    }

                    //We use ToList() because we will be modifying the original collection
                    foreach (var expressionStatement in blockStatement.Descendants.OfType <ExpressionStatement>().ToList())
                    {
                        var invocationExpression = expressionStatement.Expression as InvocationExpression;
                        if (invocationExpression == null || invocationExpression.Arguments.Count != 1)
                        {
                            continue;
                        }

                        var target = invocationExpression.Target as MemberReferenceExpression;
                        if (target == null || target.MemberName != "SetResult")
                        {
                            continue;
                        }
                        var targetExpression = target.Target as IdentifierExpression;
                        if (targetExpression == null || targetExpression.Identifier != taskCompletionSourceIdentifier)
                        {
                            continue;
                        }

                        var returnedExpression = invocationExpression.Arguments.Single();
                        returnedExpression.Remove();

                        var originalInvocation         = (InvocationExpression)invocationExpression.Annotation <OriginalNodeAnnotation>().sourceNode;
                        var originalReturnedExpression = originalInvocation.Arguments.Single();
                        var argumentType = ctx.Resolve(originalReturnedExpression).Type;

                        if (!isParameterizedTask)
                        {
                            var parent           = expressionStatement.Parent;
                            var resultIdentifier = CreateVariableName(blockStatement, "result");

                            var blockParent           = parent as BlockStatement;
                            var resultDeclarationType = argumentType == SpecialType.NullType ? new PrimitiveType("object") : CreateShortType(originalInvocation, argumentType);
                            var declaration           = new VariableDeclarationStatement(resultDeclarationType, resultIdentifier, returnedExpression);
                            if (blockParent == null)
                            {
                                var newStatement = new BlockStatement();
                                newStatement.Add(declaration);
                                newStatement.Add(new ReturnStatement());
                                expressionStatement.ReplaceWith(newStatement);
                            }
                            else
                            {
                                blockParent.Statements.InsertAfter(expressionStatement, new ReturnStatement());
                                expressionStatement.ReplaceWith(declaration);
                            }
                        }
                        else
                        {
                            var newStatement = new ReturnStatement(returnedExpression);
                            expressionStatement.ReplaceWith(newStatement);
                        }
                    }
                }

                //Find all instances of ContinueWith to replace and associated
                var continuations = new List <Tuple <InvocationExpression, InvocationExpression, string> >();

                foreach (var invocation in blockStatement.Descendants.OfType <InvocationExpression>())
                {
                    if (invocation.Arguments.Count != 1)
                    {
                        continue;
                    }

                    var originalInvocation = (InvocationExpression)invocation.Annotation <OriginalNodeAnnotation>().sourceNode;
                    if (!validInvocations.Contains(originalInvocation))
                    {
                        continue;
                    }

                    var lambda = invocation.Arguments.Single();

                    string associatedTaskName = null;

                    var lambdaParameters        = lambda.GetChildrenByRole(Roles.Parameter).Select(p => p.Name).ToList();
                    var lambdaTaskParameterName = lambdaParameters.FirstOrDefault();
                    if (lambdaTaskParameterName != null)
                    {
                        associatedTaskName = lambdaTaskParameterName;
                    }

                    continuations.Add(Tuple.Create(invocation, originalInvocation, associatedTaskName));
                }

                foreach (var continuationTuple in continuations)
                {
                    string taskName           = continuationTuple.Item3 ?? "task";
                    string effectiveTaskName  = CreateVariableName(blockStatement, taskName);
                    string resultName         = CreateVariableName(blockStatement, taskName + "Result");
                    var    continuation       = continuationTuple.Item1;
                    var    originalInvocation = continuationTuple.Item2;

                    var target            = continuation.Target.GetChildByRole(Roles.TargetExpression).Detach();
                    var awaitedExpression = new UnaryOperatorExpression(UnaryOperatorType.Await, target);
                    var replacements      = new List <Statement>();
                    var lambdaExpression  = originalInvocation.Arguments.First();
                    var continuationLambdaResolveResult = (LambdaResolveResult)ctx.Resolve(lambdaExpression);

                    if (!continuationLambdaResolveResult.HasParameterList)
                    {
                        //Lambda has no parameter, so creating a variable for the argument is not needed
                        // (since you can't use an argument that doesn't exist).
                        replacements.Add(new ExpressionStatement(awaitedExpression));
                    }
                    else
                    {
                        //Lambda has a parameter, which can either be a Task or a Task<T>.

                        var  lambdaParameter      = continuationLambdaResolveResult.Parameters[0];
                        bool isTaskIdentifierUsed = lambdaExpression.Descendants.OfType <IdentifierExpression>().Any(identifier =>
                        {
                            if (identifier.Identifier != lambdaParameter.Name)
                            {
                                return(false);
                            }
                            var identifierMre = identifier.Parent as MemberReferenceExpression;
                            return(identifierMre == null || identifierMre.MemberName != "Result");
                        });

                        var precedentTaskType = lambdaParameter.Type;

                        //We might need to separate the task creation and awaiting
                        if (isTaskIdentifierUsed)
                        {
                            //Create new task variable
                            var taskExpression = awaitedExpression.Expression;
                            taskExpression.Detach();
                            replacements.Add(new VariableDeclarationStatement(CreateShortType(lambdaExpression, precedentTaskType),
                                                                              effectiveTaskName,
                                                                              taskExpression));
                            awaitedExpression.Expression = new IdentifierExpression(effectiveTaskName);
                        }

                        if (precedentTaskType.IsParameterized)
                        {
                            //precedent is Task<T>
                            var precedentResultType = precedentTaskType.TypeArguments.First();
                            replacements.Add(new VariableDeclarationStatement(CreateShortType(originalInvocation, precedentResultType), resultName, awaitedExpression));
                        }
                        else
                        {
                            //precedent is Task
                            replacements.Add(awaitedExpression);
                        }
                    }

                    var parentStatement      = continuation.GetParent <Statement>();
                    var grandParentStatement = parentStatement.Parent;
                    var block = grandParentStatement as BlockStatement;
                    if (block == null)
                    {
                        block = new BlockStatement();
                        block.Statements.AddRange(replacements);
                        parentStatement.ReplaceWith(block);
                    }
                    else
                    {
                        foreach (var replacement in replacements)
                        {
                            block.Statements.InsertBefore(parentStatement, replacement);
                        }
                        parentStatement.Remove();
                    }

                    var       lambdaOrDelegate = continuation.Arguments.Single();
                    Statement lambdaContent;
                    if (lambdaOrDelegate is LambdaExpression)
                    {
                        lambdaContent = (Statement)lambdaOrDelegate.GetChildByRole(LambdaExpression.BodyRole);
                    }
                    else
                    {
                        lambdaContent = lambdaOrDelegate.GetChildByRole(Roles.Body);
                    }

                    foreach (var identifierExpression in lambdaContent.Descendants.OfType <IdentifierExpression>())
                    {
                        if (continuationTuple.Item3 != identifierExpression.Identifier)
                        {
                            continue;
                        }

                        var memberReference = identifierExpression.Parent as MemberReferenceExpression;

                        if (memberReference == null || memberReference.MemberName != "Result")
                        {
                            identifierExpression.ReplaceWith(new IdentifierExpression(effectiveTaskName));
                            continue;
                        }

                        memberReference.ReplaceWith(new IdentifierExpression(resultName));
                    }

                    if (lambdaContent is BlockStatement)
                    {
                        Statement previousStatement = replacements.Last();
                        foreach (var statementInContinuation in lambdaContent.GetChildrenByRole(BlockStatement.StatementRole))
                        {
                            statementInContinuation.Detach();
                            block.Statements.InsertAfter(previousStatement, statementInContinuation);
                            previousStatement = statementInContinuation;
                        }
                    }
                    else
                    {
                        lambdaContent.Detach();
                        block.Statements.InsertAfter(replacements.Last(), lambdaContent);
                    }
                }
            }
Exemple #59
0
        /// <summary>
        /// Evaluates an expression against the specified entity.
        /// </summary>
        /// <typeparam name="TEntity">Entity type</typeparam>
        /// <param name="conditionExpression">The condition expression.</param>
        /// <param name="entity">The entity.</param>
        /// <returns>True if the expression holds true, otherwise false.</returns>
        private bool Evaluate <TEntity>(IConditionExpression conditionExpression, TEntity entity)
        {
            bool result = false;

            BinaryOperatorExpression binaryOperatorExpression = conditionExpression as BinaryOperatorExpression;

            if (binaryOperatorExpression != null)
            {
                string leftStr, rightStr;
                bool   leftResult, rightResult;

                switch (binaryOperatorExpression.Operator)
                {
                case BinaryExpressionOperator.Equal:
                    leftStr  = GetExpressionValue(binaryOperatorExpression.Left, entity);
                    rightStr = GetExpressionValue(binaryOperatorExpression.Right, entity);
                    result   = leftStr == rightStr;
                    break;

                case BinaryExpressionOperator.NotEqual:
                    leftStr  = GetExpressionValue(binaryOperatorExpression.Left, entity);
                    rightStr = GetExpressionValue(binaryOperatorExpression.Right, entity);
                    result   = leftStr != rightStr;
                    break;

                case BinaryExpressionOperator.Contains:
                    leftStr  = GetExpressionValue(binaryOperatorExpression.Left, entity);
                    rightStr = GetExpressionValue(binaryOperatorExpression.Right, entity);
                    result   = leftStr.Contains(rightStr);
                    break;

                case BinaryExpressionOperator.Matches:
                    leftStr  = GetExpressionValue(binaryOperatorExpression.Left, entity);
                    rightStr = GetExpressionValue(binaryOperatorExpression.Right, entity);
                    Regex regex = new Regex(rightStr);
                    result = regex.IsMatch(leftStr);
                    break;

                case BinaryExpressionOperator.And:
                    leftResult  = Evaluate(binaryOperatorExpression.Left, entity);
                    rightResult = Evaluate(binaryOperatorExpression.Right, entity);
                    result      = leftResult && rightResult;
                    break;

                case BinaryExpressionOperator.Or:
                    leftResult  = Evaluate(binaryOperatorExpression.Left, entity);
                    rightResult = Evaluate(binaryOperatorExpression.Right, entity);
                    result      = leftResult || rightResult;
                    break;

                default:
                    throw new ArgumentOutOfRangeException(
                              string.Format(
                                  Thread.CurrentThread.CurrentCulture,
                                  "Unsupported operator type {0}",
                                  binaryOperatorExpression.Operator));
                }
            }
            else
            {
                UnaryOperatorExpression unaryOperatorExpression = conditionExpression as UnaryOperatorExpression;
                if (unaryOperatorExpression != null)
                {
                    switch (unaryOperatorExpression.Operator)
                    {
                    case UnaryExpressionOperator.Negate:
                        result = !Evaluate(unaryOperatorExpression.InnerExpression, entity);
                        break;

                    default:
                        throw new ArgumentOutOfRangeException(
                                  string.Format(
                                      Thread.CurrentThread.CurrentCulture,
                                      "Unsupported operator type {0}",
                                      unaryOperatorExpression.Operator));
                    }
                }
            }

            return(result);
        }
Exemple #60
0
 public abstract StringBuilder VisitUnaryOperatorExpression(UnaryOperatorExpression unaryOperatorExpression, int data);