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; }
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); }
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); }); }
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)); }
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)); }
IEnumerable <Syntax> IAstVisitor <ILTranslationContext, IEnumerable <Syntax> > .VisitUnaryOperatorExpression(UnaryOperatorExpression unaryOperatorExpression, ILTranslationContext data) => OnVisiting(data, unaryOperatorExpression, VisitingUnaryOperatorExpression) ?? OnVisited(data, unaryOperatorExpression, VisitedUnaryOperatorExpression, TranslateUnaryOperatorExpression(unaryOperatorExpression, data));
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; }
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); }
public virtual object VisitUnaryOperatorExpression(UnaryOperatorExpression unaryOperatorExpression, object data) { throw new global::System.NotImplementedException("UnaryOperatorExpression"); }
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); }
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); }
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; }
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)); }
// IMPORTANT NOTE: // The grammar consists of a few LALR(1) conflicts. These issues are, however, correctly handled, due to the fact that the grammar // is defined in a specific order making the already added parser actions have precedence over the other. // // Known conflicts that are correctly handled: // // - ELSE: Shift/Reduce conflict Dangling ELSE problem. Lots of articles are around on the internet. // The shift action is taken here. // // - CLOSE_PARENS: Shift/Reduce conflict. This is due to the fact that the explicit cast expression is like the parenthesized // expression. The shift action is taken here. // // - STAR: Reduce/Reduce conflict, between VariableType -> TypeNameExpression and PrimaryExpression -> TypeNameExpression, // due to the fact variable types can have '*', and look therefore like a binary operator expression. // The first reduce action is taken here. public CSharpGrammar() { // Please let me know if there is a better way of tidying this :s TokenMapping.Add((int)ERROR, Error); #region Definitions to use later var statementList = new GrammarDefinition("StatementList"); var statementListOptional = new GrammarDefinition("StatementListOptional", rule: null | statementList); var blockStatement = new GrammarDefinition("BlockStatement"); var variableDeclarator = new GrammarDefinition("VariableDeclarator"); var variableDeclaratorList = new GrammarDefinition("VariableDeclaratorList"); variableDeclaratorList.Rule = variableDeclarator | variableDeclaratorList + ToElement(COMMA) + variableDeclarator; var variableDeclaration = new GrammarDefinition("VariableDeclaration"); var variableInitializer = new GrammarDefinition("VariableInitializer"); var arrayInitializer = new GrammarDefinition("ArrayInitializer"); var arrayInitializerOptional = new GrammarDefinition("ArrayInitializerOptional", rule: null | arrayInitializer); var identifierInsideBody = new GrammarDefinition("IdentifierInsideBody", rule: ToElement(IDENTIFIER), createNode: node => ToIdentifier(node.Children[0].Result)); var identifierInsideBodyOptional = new GrammarDefinition("IdentifierInsideBodyOptional", rule: null | identifierInsideBody); variableDeclarator.Rule = identifierInsideBody | identifierInsideBody + ToElement(EQUALS) + variableInitializer; variableDeclarator.ComputeResult = node => { var result = new VariableDeclarator((Identifier) node.Children[0].Result); if (node.Children.Count > 1) { result.OperatorToken = (AstToken) node.Children[1].Result; result.Value = (Expression) node.Children[2].Result; } return result; }; var typeReference = new GrammarDefinition("TypeReference"); var identifierExpression = new GrammarDefinition("IdentifierExpression", rule: identifierInsideBody, createNode: node => new IdentifierExpression((Identifier) node.Children[0].Result)); var usingDirectiveListOptional = new GrammarDefinition("UsingDirectiveListOptional"); #endregion #region Type References var namespaceOrTypeExpression = new GrammarDefinition("NamespaceOrTypeExpression"); namespaceOrTypeExpression.Rule = identifierExpression | namespaceOrTypeExpression + ToElement(DOT) + ToElement(IDENTIFIER); namespaceOrTypeExpression.ComputeResult = node => { if (node.Children.Count == 1) return ToTypeReference((IConvertibleToType) node.Children[0].Result); var result = new MemberTypeReference(); result.Target = (TypeReference) node.Children[0].Result; result.AddChild(AstNodeTitles.Accessor, node.Children[1].Result); result.Identifier = ToIdentifier(node.Children[2].Result); return result; }; ComputeResultDelegate createPrimitiveTypeExpression = node => { if (node.Children[0].Result is PrimitiveTypeReference) return node.Children[0].Result; return new PrimitiveTypeReference { Identifier = ToIdentifier(node.Children[0].Result), PrimitiveType = CSharpLanguage.PrimitiveTypeFromString(((AstToken) node.Children[0].Result).Value) }; }; var integralType = new GrammarDefinition("IntegralType", rule: ToElement(SBYTE) | ToElement(BYTE) | ToElement(SHORT) | ToElement(USHORT) | ToElement(INT) | ToElement(UINT) | ToElement(LONG) | ToElement(ULONG) | ToElement(CHAR), createNode: createPrimitiveTypeExpression); var primitiveType = new GrammarDefinition("PrimitiveTypeExpression", rule: ToElement(OBJECT) | ToElement(STRING) | ToElement(BOOL) | ToElement(DECIMAL) | ToElement(FLOAT) | ToElement(DOUBLE) | ToElement(VOID) | integralType, createNode: createPrimitiveTypeExpression); var dimensionSeparators = new GrammarDefinition("DimensionSeparators"); dimensionSeparators.Rule = ToElement(COMMA) | dimensionSeparators + ToElement(COMMA); var rankSpecifier = new GrammarDefinition("RankSpecifier", rule: ToElement(OPEN_BRACKET) + ToElement(CLOSE_BRACKET) | ToElement(OPEN_BRACKET) + dimensionSeparators + ToElement(CLOSE_BRACKET), createNode: node => { var result = new ArrayTypeRankSpecifier(); result.LeftBracket = (AstToken) node.Children[0].Result; if (node.Children.Count == 3) { foreach (var dimensionSeparator in node.Children[1].GetAllNodesFromListDefinition() .Select(x => x.Result)) { result.Dimensions++; result.AddChild(AstNodeTitles.ElementSeparator, dimensionSeparator); } } result.RightBracket = (AstToken) node.Children[node.Children.Count - 1].Result; return result; }); var arrayType = new GrammarDefinition("ArrayType", rule: typeReference + rankSpecifier, createNode: node => new ArrayTypeReference() { BaseType = (TypeReference) node.Children[0].Result, RankSpecifier = (ArrayTypeRankSpecifier) node.Children[1].Result }); var pointerType = new GrammarDefinition("PointerType", rule: typeReference + ToElement(STAR), createNode: node => new PointerTypeReference() { BaseType = (TypeReference) node.Children[0].Result, PointerToken = (AstToken) node.Children[1].Result }); var typeExpression = new GrammarDefinition("TypeExpression", rule: namespaceOrTypeExpression | primitiveType); typeReference.Rule = typeExpression | arrayType | pointerType ; #endregion #region Expressions ComputeResultDelegate createBinaryOperatorExpression = node => { if (node.Children.Count == 1) return node.Children[0].Result; var result = new BinaryOperatorExpression(); result.Left = (Expression) node.Children[0].Result; var operatorToken = (AstToken) (node.Children[1].Result ?? node.Children[1].Children[0].Result); result.Operator = CSharpLanguage.BinaryOperatorFromString(operatorToken.Value); result.OperatorToken = (AstToken) operatorToken; result.Right = (Expression) node.Children[2].Result; return result; }; var expression = new GrammarDefinition("Expression"); var expressionOptional = new GrammarDefinition("ExpressionOptional", rule: null | expression); var primaryExpression = new GrammarDefinition("PrimaryExpression"); var primitiveExpression = new GrammarDefinition("PrimitiveExpression", rule: ToElement(LITERAL) | ToElement(TRUE) | ToElement(FALSE) | ToElement(NULL), createNode: node => { object interpretedValue; node.Children[0].Result.UserData.TryGetValue("InterpretedValue", out interpretedValue); var result = new PrimitiveExpression(interpretedValue, ((AstToken) node.Children[0].Result).Value, node.Children[0].Range); return result; }); var parenthesizedExpression = new GrammarDefinition("ParenthesizedExpression", rule: ToElement(OPEN_PARENS) + expression + ToElement(CLOSE_PARENS) | ToElement(OPEN_PARENS) + Error + ToElement(CLOSE_PARENS), createNode: node => new ParenthesizedExpression { LeftParenthese = (AstToken) node.Children[0].Result, Expression = (Expression) node.Children[1].Result, RightParenthese = (AstToken) node.Children[2].Result, }); var memberAccessorOperator = new GrammarDefinition("MemberAccessorOperator", rule: ToElement(DOT) | ToElement(OP_PTR) | ToElement(INTERR_OPERATOR)); var memberReferenceExpression = new GrammarDefinition("MemberReferenceExpression", rule: primaryExpression + memberAccessorOperator + identifierInsideBody | primaryExpression + memberAccessorOperator + Error, createNode: node => new MemberReferenceExpression { Target = (Expression) ((IConvertibleToExpression) node.Children[0].Result).ToExpression().Remove(), Accessor = CSharpLanguage.AccessorFromString(((AstToken) node.Children[1].Children[0].Result).Value), AccessorToken = (AstToken) node.Children[1].Children[0].Result, Identifier = (Identifier) node.Children[2].Result }); var argument = new GrammarDefinition("Argument", rule: expression | ToElement(REF) + expression | ToElement(OUT) + expression, createNode: node => { if (node.Children.Count > 1) { return new DirectionExpression() { DirectionToken = (AstToken) node.Children[0].Result, Direction = CSharpLanguage.DirectionFromString(((AstToken) node.Children[0].Result).Value), Expression = (Expression) node.Children[1].Result }; } return node.Children[0].Result; }); var argumentList = new GrammarDefinition("ArgumentList"); argumentList.Rule = argument | argumentList + ToElement(COMMA) + argument; var argumentListOptional = new GrammarDefinition("ArgumentListOptional", rule: null | argumentList); var invocationExpression = new GrammarDefinition("InvocationExpression", rule: primaryExpression + ToElement(OPEN_PARENS) + argumentListOptional + ToElement(CLOSE_PARENS), createNode: node => { var result = new InvocationExpression() { Target = (Expression) node.Children[0].Result, LeftParenthese = (AstToken) node.Children[1].Result, }; if (node.Children[2].HasChildren) { foreach (var subNode in node.Children[2].Children[0].GetAllListAstNodes()) { if (subNode is AstToken) result.AddChild(AstNodeTitles.ElementSeparator, subNode); else result.Arguments.Add((Expression) subNode); } } result.RightParenthese = (AstToken) node.Children[3].Result; return result; }); var indexerExpression = new GrammarDefinition("IndexerExpression", rule: primaryExpression + ToElement(OPEN_BRACKET_EXPR) + argumentList + ToElement(CLOSE_BRACKET), createNode: node => { var result = new IndexerExpression() { Target = (Expression) node.Children[0].Result, LeftBracket = (AstToken) node.Children[1].Result, }; foreach (var subNode in node.Children[2].GetAllListAstNodes()) { if (subNode is AstToken) result.AddChild(AstNodeTitles.ElementSeparator, subNode); else result.Indices.Add((Expression) subNode); } result.RightBracket = (AstToken) node.Children[3].Result; return result; }); var createObjectExpression = new GrammarDefinition("CreateObjectExpression", rule: ToElement(NEW) + typeReference + ToElement(OPEN_PARENS) + argumentListOptional + ToElement(CLOSE_PARENS) + arrayInitializerOptional | ToElement(NEW) + namespaceOrTypeExpression + arrayInitializer, createNode: node => { var result = new CreateObjectExpression(); result.NewKeyword = (AstToken) node.Children[0].Result; result.Type = (TypeReference) node.Children[1].Result; if (node.Children.Count == 6) { result.LeftParenthese = (AstToken) node.Children[2].Result; if (node.Children[3].HasChildren) { foreach (var subNode in node.Children[3].Children[0].GetAllListAstNodes()) { if (subNode is AstToken) result.AddChild(AstNodeTitles.ElementSeparator, subNode); else result.Arguments.Add((Expression) subNode); } } result.RightParenthese = (AstToken) node.Children[4].Result; } var initializerNode = node.Children[node.Children.Count - 1]; if (initializerNode.HasChildren) result.Initializer = (ArrayInitializer) initializerNode.Result; return result; }); var createArrayExpression = new GrammarDefinition("CreateArrayExpression", rule: ToElement(NEW) + rankSpecifier + arrayInitializer | ToElement(NEW) + typeReference + rankSpecifier + arrayInitializer | ToElement(NEW) + typeReference + ToElement(OPEN_BRACKET_EXPR) + argumentList + ToElement(CLOSE_BRACKET) + arrayInitializerOptional , createNode: node => { var result = new CreateArrayExpression(); result.NewKeyword = (AstToken) node.Children[0].Result; switch (node.Children.Count) { case 3: { var rankSpecifierNode = (ArrayTypeRankSpecifier) node.Children[1].Result; result.LeftBracket = (AstToken) rankSpecifierNode.LeftBracket.Remove(); result.RightBracket = (AstToken) rankSpecifierNode.RightBracket.Remove(); break; } case 4: { result.Type = (TypeReference) node.Children[1].Result; var rankSpecifierNode = (ArrayTypeRankSpecifier) node.Children[2].Result; result.LeftBracket = (AstToken) rankSpecifierNode.LeftBracket.Remove(); result.RightBracket = (AstToken) rankSpecifierNode.RightBracket.Remove(); break; } case 6: { result.Type = (TypeReference) node.Children[1].Result; result.LeftBracket = (AstToken) node.Children[2].Result; if (node.Children[3].HasChildren) { foreach (var subNode in node.Children[3].Children[0].GetAllListAstNodes()) { if (subNode is AstToken) result.AddChild(AstNodeTitles.ElementSeparator, subNode); else result.Arguments.Add((Expression) subNode); } } result.RightBracket = (AstToken) node.Children[4].Result; break; } } var initializerNode = node.Children[node.Children.Count - 1]; if (initializerNode.HasChildren) result.Initializer = (ArrayInitializer) initializerNode.Result; return result; }); var primitiveTypeExpression = new GrammarDefinition("PrimitiveTypeExpression", rule: primitiveType, createNode: node => ((IConvertibleToExpression) node.Children[0].Result).ToExpression()); var typeNameExpression = new GrammarDefinition("TypeNameExpression", rule: identifierExpression | memberReferenceExpression | primitiveTypeExpression); var thisExpression = new GrammarDefinition("ThisExpression", rule: ToElement(THIS), createNode: node => new ThisReferenceExpression() { ThisKeywordToken = (AstToken) node.Children[0].Result, }); var baseExpression = new GrammarDefinition("BaseExpression", rule: ToElement(BASE), createNode: node => new BaseReferenceExpression() { BaseKeywordToken = (AstToken) node.Children[0].Result, }); var typeofExpression = new GrammarDefinition("TypeOfExpression", rule: ToElement(TYPEOF) + ToElement(OPEN_PARENS) + typeReference + ToElement(CLOSE_PARENS), createNode: node => new GetTypeExpression() { GetTypeKeywordToken = (AstToken) node.Children[0].Result, LeftParenthese = (AstToken) node.Children[1].Result, TargetType = (TypeReference) node.Children[2].Result, RightParenthese = (AstToken) node.Children[3].Result, }); var defaultExpression = new GrammarDefinition("DefaultExpression", rule: ToElement(DEFAULT) + ToElement(OPEN_PARENS) + typeReference + ToElement(CLOSE_PARENS), createNode: node => new DefaultExpression() { KeywordToken = (AstToken) node.Children[0].Result, LeftParenthese = (AstToken) node.Children[1].Result, TargetType = (TypeReference) node.Children[2].Result, RightParenthese = (AstToken) node.Children[3].Result, }); var sizeofExpression = new GrammarDefinition("SizeOfExpression", rule: ToElement(SIZEOF) + ToElement(OPEN_PARENS) + typeReference + ToElement(CLOSE_PARENS), createNode: node => new SizeOfExpression() { SizeofKeyword = (AstToken) node.Children[0].Result, LeftParenthese = (AstToken) node.Children[1].Result, TargetType = (TypeReference) node.Children[2].Result, RightParenthese = (AstToken) node.Children[3].Result, }); var checkedExpression = new GrammarDefinition("CheckedExpression", rule: ToElement(CHECKED) + ToElement(OPEN_PARENS) + expression + ToElement(CLOSE_PARENS), createNode: node => new CheckedExpression() { CheckedKeyword = (AstToken) node.Children[0].Result, LeftParenthese = (AstToken) node.Children[1].Result, TargetExpression = (Expression) node.Children[2].Result, RightParenthese = (AstToken) node.Children[3].Result, }); var uncheckedExpression = new GrammarDefinition("UncheckedExpression", rule: ToElement(UNCHECKED) + ToElement(OPEN_PARENS) + expression + ToElement(CLOSE_PARENS), createNode: node => new UncheckedExpression() { UncheckedKeyword = (AstToken) node.Children[0].Result, LeftParenthese = (AstToken) node.Children[1].Result, TargetExpression = (Expression) node.Children[2].Result, RightParenthese = (AstToken) node.Children[3].Result, }); var stackAllocExpression = new GrammarDefinition("StackAllocExpression", rule: ToElement(STACKALLOC) + typeReference + ToElement(OPEN_BRACKET_EXPR) + expression + ToElement(CLOSE_BRACKET), createNode: node => new StackAllocExpression() { StackAllocKeyword = (AstToken) node.Children[0].Result, Type = (TypeReference) node.Children[1].Result, LeftBracket = (AstToken) node.Children[2].Result, Counter = (Expression) node.Children[3].Result, RightBracket = (AstToken) node.Children[4].Result, }); var explicitAnonymousMethodParameter = new GrammarDefinition("ExplicitAnonymousMethodParameter", rule: typeReference + ToElement(IDENTIFIER), createNode: node => new ParameterDeclaration { ParameterType = (TypeReference)node.Children[0].Result, Declarator = new VariableDeclarator(ToIdentifier(node.Children[1].Result)) }); var explicitAnonymousMethodParameterList = new GrammarDefinition("ExplicitAnonymousMethodParameterList"); explicitAnonymousMethodParameterList.Rule = explicitAnonymousMethodParameter | explicitAnonymousMethodParameterList + ToElement(COMMA) + explicitAnonymousMethodParameter; var explicitAnonymousMethodParameterListOptional = new GrammarDefinition("ExplicitAnonymousMethodParameterListOptional", rule: null | explicitAnonymousMethodParameterList); var explicitAnonymousMethodSignature = new GrammarDefinition("ExplicitAnonymousMethodSignature", rule: ToElement(OPEN_PARENS) + explicitAnonymousMethodParameterListOptional + ToElement(CLOSE_PARENS)); var explicitAnonymousMethodSignatureOptional = new GrammarDefinition("ExplicitAnonymousMethodSignatureOptional", rule: null | explicitAnonymousMethodSignature); var anonymousMethodExpression = new GrammarDefinition("AnonymousMethodExpression", rule: ToElement(DELEGATE) + explicitAnonymousMethodSignatureOptional + blockStatement, createNode: node => { var result = new AnonymousMethodExpression(); result.DelegateKeyword = (AstToken) node.Children[0].Result; if (node.Children[1].HasChildren) { var signature = node.Children[1].Children[0]; result.LeftParenthese = (AstToken) signature.Children[0].Result; if (signature.Children[1].HasChildren) { foreach (var child in signature.Children[1].Children[0].GetAllListAstNodes()) { if (child is AstToken) result.AddChild(AstNodeTitles.ElementSeparator, child); else result.Parameters.Add((ParameterDeclaration) child); } } result.RightParenthese = (AstToken)signature.Children[2].Result; } result.Body = (BlockStatement) node.Children[2].Result; return result; }); var implicitAnonymousMethodParameter = new GrammarDefinition("ImplicitAnonymousMethodParameter", rule: ToElement(IDENTIFIER), createNode: node => new ParameterDeclaration { Declarator = new VariableDeclarator(ToIdentifier(node.Children[0].Result)) }); var implicitAnonymousMethodParameterList = new GrammarDefinition("ImplicitAnonymousMethodParameterList"); implicitAnonymousMethodParameterList.Rule = implicitAnonymousMethodParameter | implicitAnonymousMethodParameterList + ToElement(COMMA) + implicitAnonymousMethodParameter; var implicitAnonymousMethodParameterListOptional = new GrammarDefinition("ImplicitAnonymousMethodParameterListOptional", rule: null | implicitAnonymousMethodParameterList); var implicitAnonymousMethodSignature = new GrammarDefinition("implicitAnonymousMethodSignature", rule: implicitAnonymousMethodParameter | ToElement(OPEN_PARENS_LAMBDA) + implicitAnonymousMethodParameterList + ToElement(CLOSE_PARENS)); var anonymousMethodSignature = new GrammarDefinition("AnonymousMethodSignature", rule: implicitAnonymousMethodSignature); var anonymousFunctionBody = new GrammarDefinition("AnonymousFunctionBody", rule: expression | blockStatement); var lambdaExpression = new GrammarDefinition("LambdaExpression", rule: anonymousMethodSignature + ToElement(ARROW) + anonymousFunctionBody, createNode: node => { var result = new LambdaExpression(); result.Arrow = (AstToken)node.Children[1].Result; result.Body = node.Children[2].Result; return result; }); primaryExpression.Rule = typeNameExpression | primitiveExpression | parenthesizedExpression | invocationExpression | indexerExpression | thisExpression | baseExpression | createObjectExpression | createArrayExpression | typeofExpression | defaultExpression | sizeofExpression | checkedExpression | uncheckedExpression | stackAllocExpression | anonymousMethodExpression ; var preFixUnaryOperator = new GrammarDefinition("PreFixUnaryOperator", rule: ToElement(PLUS) | ToElement(MINUS) | ToElement(STAR) | ToElement(BANG) | ToElement(OP_INC) | ToElement(OP_DEC) | ToElement(BITWISE_AND) | ToElement(TILDE) | ToElement(AWAIT)); var postFixUnaryOperator = new GrammarDefinition("PostFixUnaryOperator", rule: ToElement(OP_INC) | ToElement(OP_DEC)); var castExpression = new GrammarDefinition("CastExpression"); var unaryOperatorExpression = new GrammarDefinition("UnaryOperatorExpression", rule: primaryExpression | castExpression | (preFixUnaryOperator + primaryExpression) | (primaryExpression + postFixUnaryOperator), createNode: node => { if (node.Children.Count == 1) return node.Children[0].Result; var result = new UnaryOperatorExpression(); var isPrefix = node.Children[0].GrammarElement == preFixUnaryOperator; if (isPrefix) { var operatorToken = ((AstToken) node.Children[0].Children[0].Result); result.Operator = CSharpLanguage.UnaryOperatorFromString(operatorToken.Value); result.OperatorToken = operatorToken; } result.Expression = (Expression) node.Children[isPrefix ? 1 : 0].Result; if (!isPrefix) { var operatorToken = (AstToken) node.Children[1].Children[0].Result; result.Operator = CSharpLanguage.UnaryOperatorFromString(operatorToken.Value, false); result.OperatorToken = operatorToken; } return result; }); castExpression.Rule = ToElement(OPEN_PARENS) + typeNameExpression + ToElement(CLOSE_PARENS) + unaryOperatorExpression; castExpression.ComputeResult = node => new ExplicitCastExpression { LeftParenthese = (AstToken) node.Children[0].Result, TargetType = ToTypeReference((IConvertibleToType) node.Children[1].Result), RightParenthese = (AstToken) node.Children[2].Result, TargetExpression = (Expression) node.Children[3].Result }; var multiplicativeOperator = new GrammarDefinition("MultiplicativeOperator", rule: ToElement(STAR) | ToElement(DIV) | ToElement(PERCENT)); var multiplicativeExpression = new GrammarDefinition("MultiplicativeExpression"); multiplicativeExpression.Rule = unaryOperatorExpression | multiplicativeExpression + multiplicativeOperator + unaryOperatorExpression; multiplicativeExpression.ComputeResult = createBinaryOperatorExpression; var additiveOperator = new GrammarDefinition("AdditiveOperator", rule: ToElement(PLUS) | ToElement(MINUS)); var additiveExpression = new GrammarDefinition("AdditiveExpression"); additiveExpression.Rule = multiplicativeExpression | additiveExpression + additiveOperator + multiplicativeExpression; additiveExpression.ComputeResult = createBinaryOperatorExpression; var shiftOperator = new GrammarDefinition("ShiftOperator", rule: ToElement(OP_SHIFT_LEFT) | ToElement(OP_SHIFT_RIGHT)); var shiftExpression = new GrammarDefinition("ShiftExpression"); shiftExpression.Rule = additiveExpression | shiftExpression + shiftOperator + additiveExpression; shiftExpression.ComputeResult = createBinaryOperatorExpression; var relationalOperator = new GrammarDefinition("RelationalOperator", rule: ToElement(OP_GT) | ToElement(OP_GE) | ToElement(OP_LT) | ToElement(OP_LE) | ToElement(IS) | ToElement(AS)); var relationalExpression = new GrammarDefinition("RelationalExpression"); relationalExpression.Rule = shiftExpression | relationalExpression + relationalOperator + shiftExpression; relationalExpression.ComputeResult = node => { if (node.Children.Count == 1) return node.Children[0].Result; var operatorToken = (CSharpAstToken) node.Children[1].Children[0].Result; switch (operatorToken.Code) { case IS: return new TypeCheckExpression() { TargetExpression = (Expression) node.Children[0].Result, IsKeyword = operatorToken, TargetType = ToTypeReference((IConvertibleToType) node.Children[2].Result) }; case AS: return new SafeCastExpression() { TargetExpression = (Expression) node.Children[0].Result, CastKeyword = operatorToken, TargetType = ToTypeReference((IConvertibleToType) node.Children[2].Result) }; default: return createBinaryOperatorExpression(node); } }; var equalityOperator = new GrammarDefinition("equalityOperator", rule: ToElement(OP_EQUALS) | ToElement(OP_NOTEQUALS)); var equalityExpression = new GrammarDefinition("EqualityExpression"); equalityExpression.Rule = relationalExpression | equalityExpression + equalityOperator + relationalExpression; equalityExpression.ComputeResult = createBinaryOperatorExpression; var logicalAndExpression = new GrammarDefinition("LogicalAndExpression"); logicalAndExpression.Rule = equalityExpression | logicalAndExpression + ToElement(BITWISE_AND) + equalityExpression; logicalAndExpression.ComputeResult = createBinaryOperatorExpression; var logicalXorExpression = new GrammarDefinition("LogicalOrExpression"); logicalXorExpression.Rule = logicalAndExpression | logicalXorExpression + ToElement(CARRET) + logicalAndExpression; logicalXorExpression.ComputeResult = createBinaryOperatorExpression; var logicalOrExpression = new GrammarDefinition("LogicalOrExpression"); logicalOrExpression.Rule = logicalXorExpression | logicalOrExpression + ToElement(BITWISE_OR) + logicalXorExpression; logicalOrExpression.ComputeResult = createBinaryOperatorExpression; var conditionalAndExpression = new GrammarDefinition("ConditionalAndExpression"); conditionalAndExpression.Rule = logicalOrExpression | conditionalAndExpression + ToElement(OP_AND) + logicalOrExpression; conditionalAndExpression.ComputeResult = createBinaryOperatorExpression; var conditionalOrExpression = new GrammarDefinition("ConditionalOrExpression"); conditionalOrExpression.Rule = conditionalAndExpression | conditionalOrExpression + ToElement(OP_OR) + conditionalAndExpression; conditionalOrExpression.ComputeResult = createBinaryOperatorExpression; var nullCoalescingExpression = new GrammarDefinition("NullCoalescingExpression"); nullCoalescingExpression.Rule = conditionalOrExpression | nullCoalescingExpression + ToElement(OP_COALESCING) + conditionalOrExpression; nullCoalescingExpression.ComputeResult = createBinaryOperatorExpression; var conditionalExpression = new GrammarDefinition("ConditionalExpression", rule: nullCoalescingExpression | nullCoalescingExpression + ToElement(INTERR) + expression + ToElement(COLON) + expression, createNode: node => node.Children.Count == 1 ? node.Children[0].Result : new ConditionalExpression { Condition = (Expression) node.Children[0].Result, OperatorToken = (AstToken) node.Children[1].Result, TrueExpression = (Expression) node.Children[2].Result, ColonToken = (AstToken) node.Children[3].Result, FalseExpression = (Expression) node.Children[4].Result }); var assignmentOperator = new GrammarDefinition("AssignmentOperator", rule: ToElement(EQUALS) | ToElement(OP_ADD_ASSIGN) | ToElement(OP_SUB_ASSIGN) | ToElement(OP_MULT_ASSIGN) | ToElement(OP_DIV_ASSIGN) | ToElement(OP_AND_ASSIGN) | ToElement(OP_OR_ASSIGN) | ToElement(OP_XOR_ASSIGN) | ToElement(OP_SHIFT_LEFT_ASSIGN) | ToElement(OP_SHIFT_RIGHT_ASSIGN)); var assignmentExpression = new GrammarDefinition("AssignmentExpression", rule: unaryOperatorExpression + assignmentOperator + expression, createNode: node => new AssignmentExpression { Target = (Expression) node.Children[0].Result, Operator = CSharpLanguage.AssignmentOperatorFromString(((AstToken) node.Children[1].Children[0].Result).Value), OperatorToken = (AstToken) node.Children[1].Children[0].Result, Value = (Expression) node.Children[2].Result, }); var fromClause = new GrammarDefinition("FromClause", rule: ToElement(FROM) + identifierInsideBody + ToElement(IN) + expression, createNode: node => new LinqFromClause { FromKeyword = (AstToken) node.Children[0].Result, VariableName = (Identifier) node.Children[1].Result, InKeyword = (AstToken) node.Children[2].Result, DataSource = (Expression) node.Children[3].Result }); var letClause = new GrammarDefinition("LetClause", rule: ToElement(LET) + variableDeclarator, createNode: node => new LinqLetClause() { LetKeyword = (AstToken) node.Children[0].Result, Variable = (VariableDeclarator) node.Children[1].Result }); var whereClause = new GrammarDefinition("WhereClause", rule: ToElement(WHERE) + expression, createNode: node => new LinqWhereClause() { WhereKeyword = (AstToken) node.Children[0].Result, Condition = (Expression) node.Children[1].Result }); var orderingDirection = new GrammarDefinition("OrderingDirection", rule: null | ToElement(ASCENDING) | ToElement(DESCENDING)); var ordering = new GrammarDefinition("Ordering", rule: expression + orderingDirection, createNode: node => { var result = new LinqOrdering(); result.Expression = (Expression) node.Children[0].Result; if (node.Children[1].HasChildren) { var directionNode = node.Children[1].Children[0]; result.DirectionKeyword = (AstToken) directionNode.Result; result.Direction = directionNode.Result != null ? CSharpLanguage.OrderningDirectionFromString(result.DirectionKeyword.Value) : LinqOrderingDirection.None; } return result; }); var orderings = new GrammarDefinition("Orderings"); orderings.Rule = ordering | orderings + ToElement(COMMA) + ordering; var orderByClause = new GrammarDefinition("OrderByClause", rule: ToElement(ORDERBY) + orderings, createNode: node => { var result = new LinqOrderByClause(); result.OrderByKeyword = (AstToken) node.Children[0].Result; foreach (var subNode in node.Children[1].GetAllListAstNodes()) { if (subNode is AstToken) result.AddChild(AstNodeTitles.ElementSeparator, subNode); else result.Ordernings.Add((LinqOrdering) subNode); } return result; }); var groupByClause = new GrammarDefinition("GroupByClause", rule: ToElement(GROUP) + expression + ToElement(BY) + expression, createNode: node => new LinqGroupByClause() { GroupKeyword = (AstToken) node.Children[0].Result, Expression = (Expression) node.Children[1].Result, ByKeyword = (AstToken) node.Children[2].Result, KeyExpression = (Expression) node.Children[3].Result }); var selectClause = new GrammarDefinition("SelectClause", rule: ToElement(SELECT) + expression, createNode: node => new LinqSelectClause() { SelectKeyword = (AstToken) node.Children[0].Result, Target = (Expression) node.Children[1].Result }); var queryBodyClause = new GrammarDefinition("QueryBodyClause", rule: fromClause | letClause | groupByClause | whereClause | orderByClause ); var queryBodyClauses = new GrammarDefinition("QueryBodyClauses"); queryBodyClauses.Rule = queryBodyClause | queryBodyClauses + queryBodyClause; var queryBodyClausesOptional = new GrammarDefinition("QueryBodyClausesOptional", rule: null | queryBodyClauses); var linqExpression = new GrammarDefinition("LinqExpression", rule: fromClause + queryBodyClausesOptional + selectClause, createNode: node => { var result = new LinqExpression(); result.Clauses.Add((LinqClause) node.Children[0].Result); if (node.Children[1].HasChildren) { result.Clauses.AddRange(node.Children[1].Children[0].GetAllListAstNodes().Cast<LinqClause>()); } result.Clauses.Add((LinqClause) node.Children[2].Result); return result; }); expression.Rule = conditionalExpression | linqExpression | lambdaExpression | assignmentExpression; #endregion #region Statements var statement = new GrammarDefinition("Statement"); var embeddedStatement = new GrammarDefinition("EmbeddedStatement"); var emptyStatement = new GrammarDefinition("EmptyStatement", rule: ToElement(SEMICOLON), createNode: node => { var result = new EmptyStatement(); result.AddChild(AstNodeTitles.Semicolon, node.Children[0].Result); return result; }); var labelStatement = new GrammarDefinition("LabelStatement", rule: identifierInsideBody + ToElement(COLON), createNode: node => new LabelStatement((Identifier) node.Children[0].Result) { Colon = (AstToken) node.Children[1].Result }); var expressionStatement = new GrammarDefinition("ExpressionStatement", rule: expression + ToElement(SEMICOLON) | Error + ToElement(SEMICOLON) | Error + ToElement(CLOSE_BRACE) | expression + ToElement(CLOSE_BRACE), // Common mistake in C# is to forget the semicolon at the end of a statement. createNode: node => { var result = new ExpressionStatement(node.Children[0].Result as Expression); var endingToken = (AstToken) node.Children[1].Result; if (endingToken.GetTokenCode() == (int) SEMICOLON) { result.AddChild(AstNodeTitles.Semicolon, node.Children[1].Result); } else { node.Context.SyntaxErrors.Add(new SyntaxError( node.Children[1].Range.End, "';' expected.", MessageSeverity.Error)); node.Context.Lexer.PutBack((AstToken) endingToken); } return result; }); blockStatement.Rule = ToElement(OPEN_BRACE) + statementListOptional + ToElement(CLOSE_BRACE); blockStatement.ComputeResult = node => { var result = new BlockStatement(); result.StartScope = node.Children[0].Result; if (node.Children[1].HasChildren) { result.Statements.AddRange(node.Children[1].Children[0].GetAllListAstNodes<Statement>()); } result.EndScope = node.Children[2].Result; return result; }; var variableDeclarationStatement = new GrammarDefinition("VariableDeclarationStatement", rule: variableDeclaration + ToElement(SEMICOLON), createNode: node => { var result = node.Children[0].Result; result.AddChild(AstNodeTitles.Semicolon, node.Children[1].Result); return result; }); var ifElseStatement = new GrammarDefinition("IfElseStatement", rule: ToElement(IF) + parenthesizedExpression + embeddedStatement | ToElement(IF) + parenthesizedExpression + embeddedStatement + ToElement(ELSE) + embeddedStatement , createNode: node => { var result = new IfElseStatement(); result.IfKeyword = (AstToken) node.Children[0].Result; var parenthesized = (ParenthesizedExpression) node.Children[1].Result; result.LeftParenthese = (AstToken) parenthesized.LeftParenthese.Remove(); result.Condition = (Expression) parenthesized.Expression?.Remove(); result.RightParenthese = (AstToken) parenthesized.RightParenthese.Remove(); result.TrueBlock = (Statement) node.Children[2].Result; if (node.Children.Count > 3) { result.ElseKeyword = (AstToken) node.Children[3].Result; result.FalseBlock = (Statement) node.Children[4].Result; CheckForPossibleMistakenEmptyStatement(node.Children[4]); } else { CheckForPossibleMistakenEmptyStatement(node.Children[2]); } return result; }); var switchLabel = new GrammarDefinition("SwitchLabel", rule: ToElement(CASE) + expression + ToElement(COLON) | ToElement(DEFAULT_COLON) + ToElement(COLON), createNode: node => { var result = new SwitchCaseLabel(); result.CaseKeyword = (AstToken) node.Children[0].Result; if (node.Children.Count > 2) result.Condition = (Expression) node.Children[1].Result; result.Colon = (AstToken) node.Children[node.Children.Count - 1].Result; return result; }); var switchLabels = new GrammarDefinition("SwitchLabels"); switchLabels.Rule = switchLabel | switchLabels + switchLabel; var switchSection = new GrammarDefinition("SwitchSection", rule: switchLabels + statementList, createNode: node => { var result = new SwitchSection(); result.Labels.AddRange(node.Children[0].GetAllListAstNodes<SwitchCaseLabel>()); result.Statements.AddRange(node.Children[1].GetAllListAstNodes<Statement>()); return result; }); var switchSections = new GrammarDefinition("SwitchSections"); switchSections.Rule = switchSection | switchSections + switchSection; var switchBlock = new GrammarDefinition("SwitchBlock", rule: ToElement(OPEN_BRACE) + switchSections + ToElement(CLOSE_BRACE)); var switchStatement = new GrammarDefinition("SwitchStatement", rule: ToElement(SWITCH) + ToElement(OPEN_PARENS) + expression + ToElement(CLOSE_PARENS) + switchBlock, createNode: node => { var result = new SwitchStatement(); result.SwitchKeyword = (AstToken) node.Children[0].Result; result.LeftParenthese = (AstToken) node.Children[1].Result; result.Condition = (Expression) node.Children[2].Result; result.RightParenthese = (AstToken) node.Children[3].Result; var switchBlockNode = node.Children[4]; result.StartScope = switchBlockNode.Children[0].Result; result.Sections.AddRange(switchBlockNode.Children[1].GetAllListAstNodes<SwitchSection>()); result.EndScope = switchBlockNode.Children[2].Result; return result; }); var selectionStatement = new GrammarDefinition("SelectionStatement", rule: ifElseStatement | switchStatement); var whileLoopStatement = new GrammarDefinition("WhileLoopStatement", rule: ToElement(WHILE) + parenthesizedExpression + embeddedStatement, createNode: node => { var bodyNode = node.Children[2]; CheckForPossibleMistakenEmptyStatement(bodyNode); var conditionExpr = (ParenthesizedExpression) node.Children[1].Result; return new WhileLoopStatement { WhileKeyword = (AstToken) node.Children[0].Result, LeftParenthese = (AstToken) conditionExpr.LeftParenthese.Remove(), Condition = (Expression) conditionExpr.Expression.Remove(), RightParenthese = (AstToken) conditionExpr.RightParenthese.Remove(), Body = (Statement) bodyNode.Result }; }); var doLoopStatement = new GrammarDefinition("DoLoopStatement", rule: ToElement(DO) + embeddedStatement + ToElement(WHILE) + parenthesizedExpression + ToElement(SEMICOLON), createNode: node => { var conditionExpr = (ParenthesizedExpression) node.Children[3].Result; return new DoLoopStatement { DoKeyword = (AstToken) node.Children[0].Result, Body = (Statement) node.Children[1].Result, WhileKeyword = (AstToken) node.Children[2].Result, LeftParenthese = (AstToken) conditionExpr.LeftParenthese.Remove(), Condition = (Expression) conditionExpr.Expression.Remove(), RightParenthese = (AstToken) conditionExpr.RightParenthese.Remove(), Semicolon = (AstToken) node.Children[4].Result }; }); var forLoopInitializer = new GrammarDefinition("ForLoopInitializer", rule: variableDeclaration | null // TODO: statement-expression-list ); var forLoopCondition = new GrammarDefinition("ForLoopCondition", rule: expression | null); var forLoopStatement = new GrammarDefinition("ForLoopStatement", rule: ToElement(FOR) + ToElement(OPEN_PARENS) + forLoopInitializer + ToElement(SEMICOLON) + expressionOptional + ToElement(SEMICOLON) + expressionOptional // TODO: statement-expression-list + ToElement(CLOSE_PARENS) + embeddedStatement, createNode: node => { var result = new ForLoopStatement(); result.ForKeyword = (AstToken) node.Children[0].Result; result.LeftParenthese = (AstToken) node.Children[1].Result; if (node.Children[2].HasChildren) { var declaration = node.Children[2].Children[0].Result as VariableDeclarationStatement; if (declaration != null) { result.Initializers.Add(declaration); } else { result.Initializers.AddRange(node.Children[2].GetAllListAstNodes<Expression>() .Select(x => new ExpressionStatement(x))); } } result.AddChild(AstNodeTitles.Semicolon, node.Children[3].Result); if (node.Children[4].HasChildren) result.Condition = (Expression) node.Children[4].Result; result.AddChild(AstNodeTitles.Semicolon, node.Children[5].Result); if (node.Children[6].HasChildren) { result.Iterators.AddRange(node.Children[6].Children[0].GetAllListAstNodes<Expression>() .Select(x => new ExpressionStatement(x))); } result.RightParenthese = (AstToken) node.Children[7].Result; var bodyNode = node.Children[8]; CheckForPossibleMistakenEmptyStatement(bodyNode); result.Body = (Statement) bodyNode.Result; return result; }); var foreachLoopStatement = new GrammarDefinition("ForEachLoopStatement", rule: ToElement(FOREACH) + ToElement(OPEN_PARENS) + typeReference + identifierInsideBody + ToElement(IN) + expression + ToElement(CLOSE_PARENS) + embeddedStatement, createNode: node => { var bodyNode = node.Children[7]; CheckForPossibleMistakenEmptyStatement(bodyNode); return new ForeachLoopStatement { ForeachKeyword = (AstToken) node.Children[0].Result, LeftParenthese = (AstToken) node.Children[1].Result, Type = (TypeReference) node.Children[2].Result, Identifier = (Identifier) node.Children[3].Result, InKeyword = (AstToken) node.Children[4].Result, Target = (Expression) node.Children[5].Result, RightParenthese = (AstToken) node.Children[6].Result, Body = (Statement) bodyNode.Result }; }); var loopStatement = new GrammarDefinition("LoopStatement", rule: whileLoopStatement | doLoopStatement | forLoopStatement | foreachLoopStatement); var lockStatement = new GrammarDefinition("LockStatement", rule: ToElement(LOCK) + ToElement(OPEN_PARENS) + expression + ToElement(CLOSE_PARENS) + statement, createNode: node => { var bodyNode = node.Children[4]; CheckForPossibleMistakenEmptyStatement(bodyNode); return new LockStatement { LockKeyword = (AstToken) node.Children[0].Result, LeftParenthese = (AstToken) node.Children[1].Result, LockObject = (Expression) node.Children[2].Result, RightParenthese = (AstToken) node.Children[3].Result, Body = (Statement) bodyNode.Result }; }); var resourceAcquisition = new GrammarDefinition("ResourceAcquisition", rule: variableDeclaration | expression); var usingStatement = new GrammarDefinition("UsingStatement", rule: ToElement(USING) + ToElement(OPEN_PARENS) + resourceAcquisition + ToElement(CLOSE_PARENS) + statement, createNode: node => { var bodyNode = node.Children[4]; CheckForPossibleMistakenEmptyStatement(bodyNode); return new UsingStatement() { UsingKeyword = (AstToken) node.Children[0].Result, LeftParenthese = (AstToken) node.Children[1].Result, DisposableObject = node.Children[2].Result, RightParenthese = (AstToken) node.Children[3].Result, Body = (Statement) bodyNode.Result }; }); var breakStatement = new GrammarDefinition("BreakStatement", rule: ToElement(BREAK) + ToElement(SEMICOLON), createNode: node => new BreakStatement() { Keyword = (AstToken) node.Children[0].Result, Semicolon = (AstToken) node.Children[1].Result }); var continueStatement = new GrammarDefinition("ContinueStatement", rule: ToElement(CONTINUE) + ToElement(SEMICOLON), createNode: node => new BreakStatement() { Keyword = (AstToken) node.Children[0].Result, Semicolon = (AstToken) node.Children[1].Result }); var returnStatement = new GrammarDefinition("ReturnStatement", rule: ToElement(RETURN) + expressionOptional + ToElement(SEMICOLON), createNode: node => { var result = new ReturnStatement(); result.ReturnKeyword = (AstToken) node.Children[0].Result; if (node.Children[1].HasChildren) result.Value = (Expression) node.Children[1].Result; result.AddChild(AstNodeTitles.Semicolon, node.Children[2].Result); return result; }); var throwStatement = new GrammarDefinition("ThrowStatement", rule: ToElement(THROW) + expressionOptional + ToElement(SEMICOLON), createNode: node => { var result = new ThrowStatement(); result.ThrowKeyword = (AstToken) node.Children[0].Result; if (node.Children[1].HasChildren) result.Expression = (Expression) node.Children[1].Result; result.AddChild(AstNodeTitles.Semicolon, node.Children[2].Result); return result; }); var gotoStatement = new GrammarDefinition("GotoStatement", rule: ToElement(GOTO) + identifierInsideBody + ToElement(SEMICOLON), // TODO: goto case and goto default statements. createNode: node => { var result = new GotoStatement(); result.GotoKeyword = (AstToken) node.Children[0].Result; result.LabelIdentifier = (Identifier) node.Children[1].Result; result.AddChild(AstNodeTitles.Semicolon, node.Children[2].Result); return result; }); var jumpStatement = new GrammarDefinition("JumpStatement", rule: breakStatement | continueStatement | gotoStatement | returnStatement | throwStatement); var yieldStatement = new GrammarDefinition("YieldStatement", rule: ToElement(YIELD) + ToElement(RETURN) + expression + ToElement(SEMICOLON), createNode: node => new YieldStatement() { YieldKeyword = (AstToken) node.Children[0].Result, ReturnKeyword = (AstToken) node.Children[1].Result, Value = (Expression) node.Children[2].Result }); var yieldBreakStatement = new GrammarDefinition("YieldBreakStatement", rule: ToElement(YIELD) + ToElement(BREAK) + ToElement(SEMICOLON), createNode: node => new YieldBreakStatement() { Keyword = (AstToken) node.Children[0].Result, BreakKeyword = (AstToken) node.Children[1].Result }); var specificCatchClause = new GrammarDefinition("SpecificCatchClause", rule: ToElement(CATCH) + ToElement(OPEN_PARENS) + namespaceOrTypeExpression + identifierInsideBodyOptional + ToElement(CLOSE_PARENS) + blockStatement, createNode: node => { var result = new CatchClause(); result.CatchKeyword = (AstToken) node.Children[0].Result; result.LeftParenthese = (AstToken) node.Children[1].Result; result.ExceptionType = (TypeReference) node.Children[2].Result; if (node.Children[3].HasChildren) result.ExceptionIdentifier = (Identifier) node.Children[3].Result; result.RightParenthese = (AstToken) node.Children[4].Result; result.Body = (BlockStatement) node.Children[5].Result; return result; }); var generalCatchClause = new GrammarDefinition("GeneralCatchClause", rule: ToElement(CATCH) + blockStatement, createNode: node => new CatchClause { CatchKeyword = (AstToken) node.Children[0].Result, Body = (BlockStatement) node.Children[1].Result }); var catchClause = new GrammarDefinition("CatchClause", rule: specificCatchClause | generalCatchClause); var catchClauses = new GrammarDefinition("CatchClauses"); catchClauses.Rule = catchClause | catchClauses + catchClause; var finallyClause = new GrammarDefinition("FinallyClause", rule: ToElement(FINALLY) + blockStatement); var tryCatchStatement = new GrammarDefinition("TryCatchStatement", rule: ToElement(TRY) + blockStatement + catchClauses | ToElement(TRY) + blockStatement + finallyClause | ToElement(TRY) + blockStatement + catchClauses + finallyClause, createNode: node => { var result = new TryCatchStatement(); result.TryKeyword = (AstToken) node.Children[0].Result; result.TryBlock = (BlockStatement) node.Children[1].Result; ParserNode finallyClauseNode = null; if (node.Children[2].GrammarElement == finallyClause) { finallyClauseNode = node.Children[2]; } else { result.CatchClauses.AddRange(node.Children[2].GetAllListAstNodes<CatchClause>()); } if (node.Children.Count == 4) finallyClauseNode = node.Children[3]; if (finallyClauseNode != null) { result.FinallyKeyword = (AstToken) finallyClauseNode.Children[0].Result; result.FinallyBlock = (BlockStatement) finallyClauseNode.Children[1].Result; } return result; }); var unsafeStatement = new GrammarDefinition("UnsafeStatement", rule: ToElement(UNSAFE) + blockStatement, createNode: node => new UnsafeStatement() { Keyword = (AstToken) node.Children[0].Result, Body = (BlockStatement) node.Children[1].Result }); var fixedStatement = new GrammarDefinition("FixedStatement", rule: ToElement(FIXED) + ToElement(OPEN_PARENS) + variableDeclaration + ToElement(CLOSE_PARENS) + embeddedStatement, createNode: node => { var result = new FixedStatement(); result.Keyword = (AstToken) node.Children[0].Result; result.LeftParenthese = (AstToken) node.Children[1].Result; result.VariableDeclaration = (VariableDeclarationStatement) node.Children[2].Result; result.RightParenthese = (AstToken) node.Children[3].Result; var bodyNode = node.Children[4]; result.Body = (Statement) bodyNode.Result; CheckForPossibleMistakenEmptyStatement(bodyNode); return result; }); embeddedStatement.Rule = emptyStatement | expressionStatement | blockStatement | selectionStatement | loopStatement | jumpStatement | lockStatement | usingStatement | yieldStatement | yieldBreakStatement | tryCatchStatement | unsafeStatement | fixedStatement ; statement.Rule = variableDeclarationStatement | labelStatement | embeddedStatement; ; #endregion #region Members var customAttribute = new GrammarDefinition("CustomAttribute", rule: namespaceOrTypeExpression | namespaceOrTypeExpression + ToElement(OPEN_PARENS) + argumentListOptional + ToElement(CLOSE_PARENS), createNode: node => { var result = new CustomAttribute(); result.Type = ((IConvertibleToType) node.Children[0].Result).ToTypeReference(); if (node.Children.Count > 1) { result.LeftParenthese = (AstToken) node.Children[1].Result; if (node.Children[2].HasChildren) { foreach (var child in node.Children[2].Children[0].GetAllListAstNodes()) { if (child is AstToken) result.AddChild(AstNodeTitles.ElementSeparator, child); else result.Arguments.Add((Expression) child); } } result.RightParenthese = (AstToken) node.Children[3].Result; } return result; }); var customAttributeList = new GrammarDefinition("CustomAttributeList"); customAttributeList.Rule = customAttribute | customAttributeList + ToElement(COMMA) + customAttribute; var customAttributePrefix = new GrammarDefinition("CustomAttributePrefix", rule: ToElement(ASSEMBLY) | ToElement(MODULE)); var customAttributePrefixOptional = new GrammarDefinition("CustomAttributePrefixOptional", rule: null | customAttributePrefix + ToElement(COLON)); var customAttributeSection = new GrammarDefinition("CustomAttributeSection", rule: ToElement(OPEN_BRACKET_EXPR) // HACK: use expression brackets instead to avoid conflicts. + customAttributePrefixOptional + customAttributeList + ToElement(CLOSE_BRACKET), createNode: node => { var result = new CustomAttributeSection(); result.LeftBracket = (AstToken) node.Children[0].Result; if (node.Children[1].Result != null) { result.VariantKeyword = (AstToken) node.Children[1].Result; result.Variant = CSharpLanguage.SectionVariantFromString(result.VariantKeyword.Value); } foreach (var child in node.Children[2].GetAllListAstNodes()) { if (child is AstToken) result.AddChild(AstNodeTitles.ElementSeparator, child); else result.Attributes.Add((CustomAttribute) child); } result.RightBracket = (AstToken) node.Children[3].Result; return result; }); var customAttributeSectionList = new GrammarDefinition("CustomAttributeSectionList"); customAttributeSectionList.Rule = customAttributeSection | customAttributeSectionList + customAttributeSection; var customAttributeSectionListOptional = new GrammarDefinition("CustomAttributeSectionListOptional", rule: null | customAttributeSectionList); var modifier = new GrammarDefinition("Modifier", rule: ToElement(PRIVATE) | ToElement(PROTECTED) | ToElement(INTERNAL) | ToElement(PUBLIC) | ToElement(STATIC) | ToElement(ABSTRACT) | ToElement(OVERRIDE) | ToElement(PARTIAL) | ToElement(CONST) | ToElement(READONLY) | ToElement(VIRTUAL) | ToElement(SEALED) | ToElement(UNSAFE) | ToElement(FIXED) | ToElement(ASYNC) | ToElement(EXTERN), createNode: node => new ModifierElement(((AstToken) node.Children[0].Result).Value, node.Children[0].Range) { Modifier = CSharpLanguage.ModifierFromString(((AstToken) node.Children[0].Result).Value) }); var modifierList = new GrammarDefinition("ModifierList"); modifierList.Rule = modifier | modifierList + modifier; var modifierListOptional = new GrammarDefinition("ModifierListOptional", rule: null | modifierList); var fieldDeclaration = new GrammarDefinition("FieldDeclaration", rule: customAttributeSectionListOptional + modifierListOptional + typeReference + variableDeclaratorList + ToElement(SEMICOLON), createNode: node => { var result = new FieldDeclaration(); if (node.Children[0].HasChildren) result.CustomAttributeSections.AddRange(node.Children[0].Children[0].GetAllListAstNodes<CustomAttributeSection>()); if (node.Children[1].HasChildren) result.ModifierElements.AddRange(node.Children[1].Children[0].GetAllListAstNodes<ModifierElement>()); result.FieldType = (TypeReference) node.Children[2].Result; foreach (var subNode in node.Children[3].GetAllListAstNodes()) { if (subNode is AstToken) result.AddChild(AstNodeTitles.ElementSeparator, subNode); else result.Declarators.Add((VariableDeclarator) subNode); } result.AddChild(AstNodeTitles.Semicolon, node.Children[4].Result); return result; }); var parameterModifier = new GrammarDefinition("ParameterModifier", rule: null | ToElement(THIS) | ToElement(REF) | ToElement(OUT) | ToElement(PARAMS)); var parameterDeclaration = new GrammarDefinition("ParameterDeclaration", rule: customAttributeSectionListOptional + parameterModifier + typeReference + variableDeclarator, createNode: node => { var result = new ParameterDeclaration(); if (node.Children[0].HasChildren) { result.CustomAttributeSections.AddRange( node.Children[0].Children[0].GetAllListAstNodes<CustomAttributeSection>()); } result.ParameterModifierToken = (AstToken) (node.Children[1].HasChildren ? node.Children[1].Children[0].Result : null); result.ParameterType = (TypeReference) node.Children[2].Result; result.Declarator = (VariableDeclarator) node.Children[3].Result; return result; }); var parameterDeclarationList = new GrammarDefinition("ParameterDeclarationList"); parameterDeclarationList.Rule = parameterDeclaration | parameterDeclarationList + ToElement(COMMA) + parameterDeclaration; var optionalParameterDeclarationList = new GrammarDefinition("OptionalParameterDeclarationList", rule: null | parameterDeclarationList); var constructorInitializerVariant = new GrammarDefinition("ConstructorInitializerVariant", rule: ToElement(THIS) | ToElement(BASE)); var constructorInitializer = new GrammarDefinition("ConstructorInitializer", rule: constructorInitializerVariant + ToElement(OPEN_PARENS) + argumentListOptional + ToElement(CLOSE_PARENS), createNode: node => { var result = new Members.ConstructorInitializer(); result.VariantToken = (AstToken) node.Children[0].Children[0].Result; result.LeftParenthese = (AstToken) node.Children[1].Result; if (node.Children[2].HasChildren) { foreach (var subNode in node.Children[2].Children[0].GetAllListAstNodes()) { if (subNode is AstToken) result.AddChild(AstNodeTitles.ElementSeparator, subNode); else result.Arguments.Add((Expression) subNode); } } result.RightParenthese = (AstToken) node.Children[3].Result; return result; }); var optionalConstructorInitializerList = new GrammarDefinition("OptionalConstructorInitializer", rule: null | ToElement(COLON) + constructorInitializer); var constructorDeclaration = new GrammarDefinition("ConstructorDeclaration", rule: customAttributeSectionListOptional + modifierListOptional + ToElement(IDENTIFIER) + ToElement(OPEN_PARENS) + optionalParameterDeclarationList + ToElement(CLOSE_PARENS) + optionalConstructorInitializerList + blockStatement, createNode: node => { var result = new Members.ConstructorDeclaration(); if (node.Children[0].HasChildren) result.CustomAttributeSections.AddRange(node.Children[0].Children[0].GetAllListAstNodes<CustomAttributeSection>()); if (node.Children[1].HasChildren) result.ModifierElements.AddRange(node.Children[1].Children[0].GetAllListAstNodes<ModifierElement>()); result.Identifier = ToIdentifier(node.Children[2].Result); result.LeftParenthese = (AstToken) node.Children[3].Result; if (node.Children[4].HasChildren) { foreach (var subNode in node.Children[4].Children[0].GetAllListAstNodes()) { if (subNode is AstToken) result.AddChild(AstNodeTitles.ElementSeparator, subNode); else result.Parameters.Add((ParameterDeclaration) subNode); } } result.RightParenthese = (AstToken) node.Children[5].Result; if (node.Children[6].HasChildren) { result.Colon = (AstToken) node.Children[6].Children[0].Result; result.Initializer = (Members.ConstructorInitializer) node.Children[6].Children[1].Result; } result.Body = (BlockStatement) node.Children[7].Result; return result; }); var conversionOperator = new GrammarDefinition("ConversionOperator", rule: ToElement(IMPLICIT) | ToElement(EXPLICIT)); var conversionOperatorDeclaration = new GrammarDefinition("ConversionOperatorDeclaration", rule: customAttributeSectionListOptional + modifierListOptional + conversionOperator + ToElement(OPERATOR) + ToElement(IDENTIFIER) + ToElement(OPEN_PARENS) + optionalParameterDeclarationList + ToElement(CLOSE_PARENS) + blockStatement, createNode: node => { var result = new OperatorDeclaration(); if (node.Children[0].HasChildren) result.CustomAttributeSections.AddRange(node.Children[0].Children[0].GetAllListAstNodes<CustomAttributeSection>()); if (node.Children[1].HasChildren) result.ModifierElements.AddRange(node.Children[1].Children[0].GetAllListAstNodes<ModifierElement>()); result.Identifier = ToIdentifier(node.Children[2].Result); result.OperatorType = CSharpLanguage.OperatorDeclarationTypeFromString(result.Identifier.Name); result.OperatorKeyword = (AstToken) node.Children[3].Result; result.ReturnType = ToTypeReference(ToIdentifier(node.Children[4].Result)); result.LeftParenthese = (AstToken)node.Children[5].Result; if (node.Children[6].HasChildren) { foreach (var subNode in node.Children[6].Children[0].GetAllListAstNodes()) { if (subNode is AstToken) result.AddChild(AstNodeTitles.ElementSeparator, subNode); else result.Parameters.Add((ParameterDeclaration)subNode); } } result.RightParenthese = (AstToken) node.Children[7].Result; result.Body = (BlockStatement) node.Children[8].Result; return result; }); var overloadableOperator = new GrammarDefinition("OverloadableOperator", rule: ToElement(PLUS) | ToElement(MINUS) | ToElement(STAR) | ToElement(DIV) | ToElement(PERCENT) | ToElement(BITWISE_AND) | ToElement(BITWISE_OR) | ToElement(CARRET) | ToElement(OP_EQUALS) | ToElement(OP_NOTEQUALS) | ToElement(OP_GT) | ToElement(OP_GE) | ToElement(OP_LT) | ToElement(OP_LE) | ToElement(OP_SHIFT_LEFT) | ToElement(OP_SHIFT_RIGHT) | ToElement(TRUE) | ToElement(FALSE) | ToElement(BANG) | ToElement(TILDE) | ToElement(OP_INC) | ToElement(OP_DEC)); var arithmeticOperatorDeclaration = new GrammarDefinition("ArithmeticOperatorDeclaration", rule: customAttributeSectionListOptional + modifierListOptional + typeReference + ToElement(OPERATOR) + overloadableOperator + ToElement(OPEN_PARENS) + optionalParameterDeclarationList + ToElement(CLOSE_PARENS) + blockStatement, createNode: node => { var result = new OperatorDeclaration(); if (node.Children[0].HasChildren) result.CustomAttributeSections.AddRange(node.Children[0].Children[0].GetAllListAstNodes<CustomAttributeSection>()); if (node.Children[1].HasChildren) result.ModifierElements.AddRange(node.Children[1].Children[0].GetAllListAstNodes<ModifierElement>()); result.ReturnType = (TypeReference) node.Children[2].Result; result.OperatorKeyword = (AstToken)node.Children[3].Result; result.Identifier = ToIdentifier(node.Children[4].Result); result.LeftParenthese = (AstToken)node.Children[5].Result; if (node.Children[6].HasChildren) { foreach (var subNode in node.Children[6].Children[0].GetAllListAstNodes()) { if (subNode is AstToken) result.AddChild(AstNodeTitles.ElementSeparator, subNode); else result.Parameters.Add((ParameterDeclaration)subNode); } } result.RightParenthese = (AstToken)node.Children[7].Result; result.OperatorType = CSharpLanguage.OperatorDeclarationTypeFromString(result.Identifier.Name); if (result.Parameters.Count == 2) { if (result.OperatorType == OperatorDeclarationType.Positive) result.OperatorType = OperatorDeclarationType.Add; else if (result.OperatorType == OperatorDeclarationType.Negative) result.OperatorType = OperatorDeclarationType.Subtract; } result.Body = (BlockStatement)node.Children[8].Result; return result; }); var operatorDeclaration = new GrammarDefinition("OperatorDeclaration", rule: conversionOperatorDeclaration | arithmeticOperatorDeclaration); var methodDeclarationBody = new GrammarDefinition("MethodDeclarationBody", rule: ToElement(SEMICOLON) | blockStatement); var methodDeclaration = new GrammarDefinition("MethodDeclaration", rule: customAttributeSectionListOptional + modifierListOptional + typeReference + ToElement(IDENTIFIER) + ToElement(OPEN_PARENS) + optionalParameterDeclarationList + ToElement(CLOSE_PARENS) + methodDeclarationBody, createNode: node => { var result = new MethodDeclaration(); if (node.Children[0].HasChildren) result.CustomAttributeSections.AddRange(node.Children[0].Children[0].GetAllListAstNodes<CustomAttributeSection>()); if (node.Children[1].HasChildren) result.ModifierElements.AddRange(node.Children[1].Children[0].GetAllListAstNodes<ModifierElement>()); result.ReturnType = (TypeReference) node.Children[2].Result; result.Identifier = ToIdentifier(node.Children[3].Result); result.LeftParenthese = (AstToken) node.Children[4].Result; if (node.Children[5].HasChildren) { foreach (var subNode in node.Children[5].Children[0].GetAllListAstNodes()) { if (subNode is AstToken) result.AddChild(AstNodeTitles.ElementSeparator, subNode); else result.Parameters.Add((ParameterDeclaration) subNode); } } result.RightParenthese = (AstToken) node.Children[6].Result; var body = node.Children[7].Result; if (body is AstToken) result.AddChild(AstNodeTitles.Semicolon, (AstToken) body); else result.Body = (BlockStatement) body; return result; }); var eventDeclaration = new GrammarDefinition("EventDeclaration", rule: customAttributeSectionListOptional + modifierListOptional + ToElement(EVENT) + typeReference + variableDeclaratorList + ToElement(SEMICOLON), createNode: node => { var result = new EventDeclaration(); if (node.Children[0].HasChildren) result.CustomAttributeSections.AddRange(node.Children[0].Children[0].GetAllListAstNodes<CustomAttributeSection>()); if (node.Children[1].HasChildren) result.ModifierElements.AddRange(node.Children[1].Children[0].GetAllListAstNodes<ModifierElement>()); result.EventKeyword = (AstToken) node.Children[2].Result; result.EventType = (TypeReference) node.Children[3].Result; foreach (var subNode in node.Children[4].GetAllListAstNodes()) { if (subNode is AstToken) result.AddChild(AstNodeTitles.ElementSeparator, subNode); else result.Declarators.Add((VariableDeclarator) subNode); } result.AddChild(AstNodeTitles.Semicolon, node.Children[5].Result); return result; }); var accessorKeyword = new GrammarDefinition("AccessorKeyword", rule: ToElement(GET) | ToElement(SET)); var accessorBody = new GrammarDefinition("AccessorBody", rule: ToElement(SEMICOLON) | blockStatement); var accessorDeclaration = new GrammarDefinition("AccessorDeclaration", rule: customAttributeSectionListOptional + modifierListOptional + accessorKeyword + accessorBody, createNode: node => { var result = new AccessorDeclaration(); if (node.Children[0].HasChildren) result.CustomAttributeSections.AddRange(node.Children[0].Children[0].GetAllListAstNodes<CustomAttributeSection>()); if (node.Children[1].HasChildren) result.ModifierElements.AddRange(node.Children[1].Children[0].GetAllListAstNodes<ModifierElement>()); result.AccessorKeyword = (AstToken) node.Children[2].Children[0].Result; var bodyNode = node.Children[3].Children[0].Result; if (bodyNode is AstToken) result.AddChild(AstNodeTitles.Semicolon, bodyNode); else result.Body = (BlockStatement) bodyNode; return result; }); var accessorDeclarationList = new GrammarDefinition("AccessorDeclarationList"); accessorDeclarationList.Rule = accessorDeclaration | accessorDeclaration + accessorDeclaration; var propertyDeclaration = new GrammarDefinition("PropertyDeclaration", rule: customAttributeSectionListOptional + modifierListOptional + typeReference + ToElement(IDENTIFIER) + ToElement(OPEN_BRACE) + accessorDeclarationList + ToElement(CLOSE_BRACE), createNode: node => { var result = new PropertyDeclaration(); if (node.Children[0].HasChildren) result.CustomAttributeSections.AddRange(node.Children[0].Children[0].GetAllListAstNodes<CustomAttributeSection>()); if (node.Children[1].HasChildren) result.ModifierElements.AddRange(node.Children[1].Children[0].GetAllListAstNodes<ModifierElement>()); result.PropertyType = (TypeReference) node.Children[2].Result; result.Identifier = ToIdentifier(node.Children[3].Result); result.StartScope = node.Children[4].Result; foreach (var accessor in node.Children[5].Children) { var declaration = (AccessorDeclaration) accessor.Result; // TODO: detect duplicate accessor declarations. switch (declaration.AccessorKeyword.Value) { case "get": result.Getter = declaration; break; case "set": result.Setter = declaration; break; } } result.EndScope = node.Children[6].Result; return result; }); var memberDeclaration = new GrammarDefinition("MemberDeclaration"); var memberDeclarationList = new GrammarDefinition("MemberDeclarationList"); memberDeclarationList.Rule = memberDeclaration | memberDeclarationList + memberDeclaration; var memberDeclarationListOptional = new GrammarDefinition("MemberDeclarationListOptional"); memberDeclarationListOptional.Rule = null | memberDeclarationList; var baseTypeList = new GrammarDefinition("BaseTypeList"); baseTypeList.Rule = typeReference | baseTypeList + ToElement(COMMA) + typeReference; var optionalBaseTypeList = new GrammarDefinition("OptionalBaseTypeList"); optionalBaseTypeList.Rule = null | ToElement(COLON) + baseTypeList; var typeVariantKeyword = new GrammarDefinition("TypeVariantKeyword", rule: ToElement(CLASS) | ToElement(STRUCT) | ToElement(INTERFACE) | ToElement(ENUM)); var typeDeclaration = new GrammarDefinition("TypeDeclaration", rule: customAttributeSectionListOptional + modifierListOptional + typeVariantKeyword + ToElement(IDENTIFIER) + optionalBaseTypeList + ToElement(OPEN_BRACE) + memberDeclarationListOptional + ToElement(CLOSE_BRACE), createNode: node => { var result = new TypeDeclaration(); if (node.Children[0].HasChildren) result.CustomAttributeSections.AddRange(node.Children[0].Children[0].GetAllListAstNodes<CustomAttributeSection>()); if (node.Children[1].HasChildren) result.ModifierElements.AddRange(node.Children[1].Children[0].GetAllListAstNodes<ModifierElement>()); var variantToken = (AstToken) node.Children[2].Children[0].Result; result.TypeVariant = CSharpLanguage.TypeVariantFromString(variantToken.Value); result.TypeVariantToken = variantToken; result.Identifier = ToIdentifier(node.Children[3].Result); if (node.Children[4].HasChildren) { result.AddChild(AstNodeTitles.Colon, node.Children[4].Children[0].Result); foreach (var child in node.Children[4].Children[1].GetAllListAstNodes()) { if (child is AstToken) result.AddChild(AstNodeTitles.ElementSeparator, child); else result.BaseTypes.Add((TypeReference) child); } } result.StartScope = node.Children[5].Result; if (node.Children[6].HasChildren) { result.Members.AddRange(node.Children[6].Children[0].GetAllListAstNodes<MemberDeclaration>()); } result.EndScope = node.Children[7].Result; return result; }); memberDeclaration.Rule = methodDeclaration | constructorDeclaration | operatorDeclaration | propertyDeclaration | eventDeclaration | fieldDeclaration | typeDeclaration ; var typeOrNamespaceDeclarationList = new GrammarDefinition("TypeOrNamespaceDeclarationList"); var typeOrNamespaceDeclarationListOptional = new GrammarDefinition("TypeOrNamespaceDeclarationListOptional", rule: null | typeOrNamespaceDeclarationList); var namespaceDeclaration = new GrammarDefinition("NamespaceDeclaration", rule: ToElement(NAMESPACE) + typeNameExpression + ToElement(OPEN_BRACE) + usingDirectiveListOptional + typeOrNamespaceDeclarationListOptional + ToElement(CLOSE_BRACE), createNode: node => { var result = new NamespaceDeclaration(); result.Keyword = (AstToken) node.Children[0].Result; result.Identifier = ((IConvertibleToIdentifier) node.Children[1].Result).ToIdentifier(); result.StartScope = node.Children[2].Result; if (node.Children[3].HasChildren) { result.UsingDirectives.AddRange(node.Children[3].Children[0].GetAllListAstNodes<UsingDirective>()); } if (node.Children[4].HasChildren) { foreach (var subNode in node.Children[4].Children[0].GetAllListAstNodes()) { var type = subNode as TypeDeclaration; if (type != null) result.Types.Add(type); else result.Namespaces.Add((NamespaceDeclaration) subNode); } } result.EndScope = node.Children[5].Result; return result; }); var typeOrNamespaceDeclaration = new GrammarDefinition("TypeOrNamespaceDeclaration", rule: namespaceDeclaration | typeDeclaration); typeOrNamespaceDeclarationList.Rule = typeOrNamespaceDeclaration | typeOrNamespaceDeclarationList + typeOrNamespaceDeclaration; #endregion #region Initialize definitions var variableInitializerList = new GrammarDefinition("VariableInitializerList"); variableInitializerList.Rule = variableInitializer | variableInitializerList + ToElement(COMMA) + variableInitializer; var variableInitializerListOptional = new GrammarDefinition("VariableInitializerListOptional", rule: null | variableInitializerList); arrayInitializer.Rule = ToElement(OPEN_BRACE) + variableInitializerListOptional + ToElement(CLOSE_BRACE) | ToElement(OPEN_BRACE) + variableInitializerList + ToElement(COMMA) + ToElement(CLOSE_BRACE); arrayInitializer.ComputeResult = node => { var result = new ArrayInitializer(); result.OpeningBrace = node.Children[0].Result; ParserNode initializersNode = null; if (node.Children.Count == 4) { initializersNode = node.Children[1]; } else { if (node.Children[1].HasChildren) initializersNode = node.Children[1].Children[0]; } if (initializersNode != null) { foreach (var element in initializersNode.GetAllListAstNodes()) { if (element is AstToken) result.AddChild(AstNodeTitles.ElementSeparator, element); else result.Elements.Add((Expression) element); } } if (node.Children.Count == 4) result.AddChild(AstNodeTitles.ElementSeparator, node.Children[2].Result); result.ClosingBrace = node.Children[node.Children.Count - 1].Result; return result; }; variableInitializer.Rule = expression | arrayInitializer ; var variableType = new GrammarDefinition("VariableType"); variableType.Rule = typeNameExpression | variableType + rankSpecifier | variableType + ToElement(STAR); variableType.ComputeResult = node => { var type = ToTypeReference((IConvertibleToType) node.Children[0].Result); if (node.Children.Count > 1) { var specifier = node.Children[1].Result as ArrayTypeRankSpecifier; if (specifier != null) { type = new ArrayTypeReference(type, specifier); } else { type = new PointerTypeReference(type) { PointerToken = (AstToken) node.Children[1].Result }; } } return type; }; // Types are recognized as expressions to prevent a conflict in the grammar. // TODO: also support array and pointer types. variableDeclaration.Rule = variableType + variableDeclaratorList; variableDeclaration.ComputeResult = node => { var result = new VariableDeclarationStatement(); result.VariableType = ToTypeReference((IConvertibleToType)node.Children[0].Result); foreach (var subNode in node.Children[1].GetAllListAstNodes()) { if (subNode is AstToken) result.AddChild(AstNodeTitles.ElementSeparator, subNode); else result.Declarators.Add((VariableDeclarator) subNode); } return result; }; statementList.Rule = statement | statementList + statement; #endregion #region Root compilation unit var usingNamespaceDirective = new GrammarDefinition("UsingNamespaceDirective", rule: ToElement(USING) + namespaceOrTypeExpression + ToElement(SEMICOLON), createNode: node => { var result = new UsingNamespaceDirective(); result.UsingKeyword = (AstToken) node.Children[0].Result; result.NamespaceIdentifier = ((IConvertibleToIdentifier) node.Children[1].Result).ToIdentifier(); result.AddChild(AstNodeTitles.Semicolon, node.Children[2].Result); return result; }); var usingAliasDirective = new GrammarDefinition("UsingAliasDirective", rule: ToElement(USING) + ToElement(IDENTIFIER) + ToElement(EQUALS) + typeReference + ToElement(SEMICOLON), createNode: node => { var result = new UsingAliasDirective { UsingKeyword = (AstToken) node.Children[0].Result, AliasIdentifier = ToIdentifier(node.Children[1].Result), OperatorToken = (AstToken) node.Children[2].Result, TypeImport = (TypeReference) node.Children[3].Result }; result.AddChild(AstNodeTitles.Semicolon, node.Children[4].Result); return result; }); var usingDirective = new GrammarDefinition("UsingNamespaceDirective", rule: usingNamespaceDirective | usingAliasDirective); var usingDirectiveList = new GrammarDefinition("UsingDirectiveList"); usingDirectiveList.Rule = usingDirective | usingDirectiveList + usingDirective; usingDirectiveListOptional.Rule = null | usingDirectiveList; var compilationUnit = new GrammarDefinition("CompilationUnit", rule: usingDirectiveListOptional + typeOrNamespaceDeclarationListOptional, createNode: node => { var result = new CompilationUnit(); if (node.Children[0].HasChildren) { result.UsingDirectives.AddRange(node.Children[0].Children[0].GetAllListAstNodes<UsingDirective>()); } if (node.Children[1].HasChildren) { foreach (var subNode in node.Children[1].Children[0].GetAllListAstNodes()) { var typeDecl = subNode as TypeDeclaration; if (typeDecl == null) result.Namespaces.Add((NamespaceDeclaration) subNode); else result.Types.Add(typeDecl); } } return result; }); #endregion RootDefinitions.Add(DefaultRoot = compilationUnit); RootDefinitions.Add(MemberDeclarationRule = memberDeclaration); RootDefinitions.Add(StatementRule = statement); }
public string _Visit(UnaryOperatorType op) { return(UnaryOperatorExpression.GetOperatorRole(op).Token); }
bool IsUnaryModifierExpression(UnaryOperatorExpression expr) { return expr.Operator == UnaryOperatorType.Increment || expr.Operator == UnaryOperatorType.PostIncrement || expr.Operator == UnaryOperatorType.Decrement || expr.Operator == UnaryOperatorType.PostDecrement; }
public override void VisitUnaryOperatorExpression(UnaryOperatorExpression unaryOperatorExpression) { new UnaryOperatorBlock(this, unaryOperatorExpression).Emit(); }
public override object VisitUnaryOperatorExpression(UnaryOperatorExpression unaryOperatorExpression, object data) { return(base.VisitUnaryOperatorExpression(unaryOperatorExpression, data)); }
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); }
public override AstNode VisitUnaryOperatorExpression(UnaryOperatorExpression unaryOperatorExpression, ILGenerator data) { return(_constructorEmitter.EmitUnaryOperatorExpression(unaryOperatorExpression, data)); }
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); }
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); } } }
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(); }
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))); }
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); }
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; }
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(); }
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); } }
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; }
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; }
public virtual T Visit(UnaryOperatorExpression unaryOperatorExpression) { return(VisitChildren(unaryOperatorExpression)); }
public virtual void VisitUnaryOperatorExpression (UnaryOperatorExpression unaryOperatorExpression) { VisitChildren (unaryOperatorExpression); }
public UnaryOperatorBlock(IEmitter emitter, UnaryOperatorExpression unaryOperatorExpression) : base(emitter, unaryOperatorExpression) { this.Emitter = emitter; this.UnaryOperatorExpression = unaryOperatorExpression; }
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)); }
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) }; }
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); } } }
/// <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); }
public abstract StringBuilder VisitUnaryOperatorExpression(UnaryOperatorExpression unaryOperatorExpression, int data);