// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) // This code is distributed under the GNU LGPL (for details please see \doc\license.txt) using System; using System.Collections.Generic; namespace ICSharpCode.NRefactory.VB.Ast { public abstract class Expression : AstNode { #region Null public new static readonly Expression Null = new NullExpression (); sealed class NullExpression : Expression { public override bool IsNull { get { return true; } } public override S AcceptVisitor (IAstVisitor visitor, T data) { return default (S); } protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) { return other == null || other.IsNull; } } #endregion } public class BinaryOperatorExpression : Expression { public readonly static Role LeftExpressionRole = new Role("Left"); public readonly static Role OperatorRole = new Role("Operator"); public readonly static Role RightExpressionRole = new Role("Right"); public BinaryOperatorExpression(Expression left, BinaryOperatorType type, Expression right) { AddChild(left, LeftExpressionRole); AddChild(right, RightExpressionRole); Operator = type; } public Expression Left { get { return GetChildByRole(LeftExpressionRole); } set { SetChildByRole(LeftExpressionRole, value); } } public BinaryOperatorType Operator { get; set; } public Expression Right { get { return GetChildByRole(RightExpressionRole); } set { SetChildByRole(RightExpressionRole, value); } } protected internal override bool DoMatch(AstNode other, ICSharpCode.NRefactory.PatternMatching.Match match) { throw new NotImplementedException(); } public override S AcceptVisitor(IAstVisitor visitor, T data) { return visitor.VisitBinaryOperatorExpression(this, data); } } public enum BinaryOperatorType { None, /// '&' in C#, 'And' in VB. BitwiseAnd, /// '|' in C#, 'Or' in VB. BitwiseOr, /// '&&' in C#, 'AndAlso' in VB. LogicalAnd, /// '||' in C#, 'OrElse' in VB. LogicalOr, /// '^' in C#, 'Xor' in VB. ExclusiveOr, /// > GreaterThan, /// >= GreaterThanOrEqual, /// '==' in C#, '=' in VB. Equality, /// '!=' in C#, '<>' in VB. InEquality, /// < LessThan, /// <= LessThanOrEqual, /// + Add, /// - Subtract, /// * Multiply, /// / Divide, /// '%' in C#, 'Mod' in VB. Modulus, /// VB-only: \ DivideInteger, /// VB-only: ^ Power, /// VB-only: & Concat, /// C#: << ShiftLeft, /// C#: >> ShiftRight, /// VB-only: Is ReferenceEquality, /// VB-only: IsNot ReferenceInequality, /// VB-only: Like Like, /// /// C#: ?? /// VB: IF(x, y) /// NullCoalescing, /// VB-only: ! DictionaryAccess } public class AssignmentExpression : Expression { public readonly static Role LeftExpressionRole = BinaryOperatorExpression.LeftExpressionRole; public readonly static Role OperatorRole = BinaryOperatorExpression.OperatorRole; public readonly static Role RightExpressionRole = BinaryOperatorExpression.RightExpressionRole; public AssignmentExpression(Expression left, AssignmentOperatorType type, Expression right) { AddChild(left, LeftExpressionRole); AddChild(right, RightExpressionRole); Operator = type; } public Expression Left { get { return GetChildByRole(LeftExpressionRole); } set { SetChildByRole(LeftExpressionRole, value); } } public AssignmentOperatorType Operator { get; set; } public Expression Right { get { return GetChildByRole(RightExpressionRole); } set { SetChildByRole(RightExpressionRole, value); } } protected internal override bool DoMatch(AstNode other, ICSharpCode.NRefactory.PatternMatching.Match match) { throw new NotImplementedException(); } public override S AcceptVisitor(IAstVisitor visitor, T data) { return visitor.VisitAssignmentExpression(this, data); } } /// /// Target(Arguments) /// public class InvocationExpression : Expression { public Expression Target { get { return GetChildByRole (Roles.TargetExpression); } set { SetChildByRole(Roles.TargetExpression, value); } } public AstNodeCollection Arguments { get { return GetChildrenByRole(Roles.Argument); } } public override S AcceptVisitor (IAstVisitor visitor, T data) { return visitor.VisitInvocationExpression(this, data); } public InvocationExpression () { } public InvocationExpression (Expression target, IEnumerable arguments) { AddChild (target, Roles.TargetExpression); if (arguments != null) { foreach (var arg in arguments) { AddChild (arg, Roles.Argument); } } } public InvocationExpression (Expression target, params Expression[] arguments) : this (target, (IEnumerable)arguments) { } protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) { InvocationExpression o = other as InvocationExpression; return o != null && this.Target.DoMatch(o.Target, match) && this.Arguments.DoMatch(o.Arguments, match); } } /// /// Operator Expression /// public class UnaryOperatorExpression : Expression { public readonly static Role OperatorRole = BinaryOperatorExpression.OperatorRole; public UnaryOperatorExpression() { } public UnaryOperatorExpression(UnaryOperatorType op, Expression expression) { this.Operator = op; this.Expression = expression; } public UnaryOperatorType Operator { get; set; } public VBTokenNode OperatorToken { get { return GetChildByRole (OperatorRole); } } public Expression Expression { get { return GetChildByRole (Roles.Expression); } set { SetChildByRole (Roles.Expression, value); } } public override S AcceptVisitor (IAstVisitor visitor, T data) { return visitor.VisitUnaryOperatorExpression(this, data); } protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) { UnaryOperatorExpression o = other as UnaryOperatorExpression; return o != null && this.Operator == o.Operator && this.Expression.DoMatch(o.Expression, match); } public static string GetOperatorSymbol(UnaryOperatorType op) { switch (op) { case UnaryOperatorType.Not: return "Not"; case UnaryOperatorType.Minus: return "-"; case UnaryOperatorType.Plus: return "+"; default: throw new NotSupportedException("Invalid value for UnaryOperatorType"); } } } public enum UnaryOperatorType { /// Logical/Bitwise not (Not a) Not, /// Unary minus (-a) Minus, /// Unary plus (+a) Plus } /// /// Represents a named argument passed to a method or attribute. /// public class NamedArgumentExpression : Expression { public Identifier Identifier { get { return GetChildByRole(Roles.Identifier); } set { SetChildByRole(Roles.Identifier, value); } } public VBTokenNode AssignToken { get { return GetChildByRole (Roles.Assign); } } public Expression Expression { get { return GetChildByRole (Roles.Expression); } set { SetChildByRole (Roles.Expression, value); } } public override S AcceptVisitor(IAstVisitor visitor, T data) { return visitor.VisitNamedArgumentExpression(this, data); } protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) { NamedArgumentExpression o = other as NamedArgumentExpression; return o != null && this.Identifier.DoMatch(o.Identifier, match) && this.Expression.DoMatch(o.Expression, match); } } /// /// Identifier As Type = Expression /// public class VariableInitializer : AstNode { public VariableIdentifier Identifier { get { return GetChildByRole(VariableIdentifier.VariableIdentifierRole); } set { SetChildByRole(VariableIdentifier.VariableIdentifierRole, value); } } public AstType Type { get { return GetChildByRole(Roles.Type); } set { SetChildByRole(Roles.Type, value); } } public VBTokenNode AssignToken { get { return GetChildByRole (Roles.Assign); } } public Expression Expression { get { return GetChildByRole (Roles.Expression); } set { SetChildByRole (Roles.Expression, value); } } public override S AcceptVisitor(IAstVisitor visitor, T data) { return visitor.VisitVariableInitializer(this, data); } protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) { VariableInitializer o = other as VariableInitializer; return o != null && this.Identifier.DoMatch(o.Identifier, match) && this.Expression.DoMatch(o.Expression, match); } } /// /// [ Key ] .Identifier = Expression /// public class FieldInitializerExpression : Expression { public bool IsKey { get; set; } public VBTokenNode KeyToken { get { return GetChildByRole (Roles.Keyword); } } public VBTokenNode DotToken { get { return GetChildByRole (Roles.Dot); } } public Identifier Identifier { get { return GetChildByRole(Roles.Identifier); } set { SetChildByRole(Roles.Identifier, value); } } public VBTokenNode AssignToken { get { return GetChildByRole (Roles.Assign); } } public Expression Expression { get { return GetChildByRole (Roles.Expression); } set { SetChildByRole (Roles.Expression, value); } } public override S AcceptVisitor(IAstVisitor visitor, T data) { return visitor.VisitFieldInitializerExpression(this, data); } protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) { FieldInitializerExpression o = other as FieldInitializerExpression; return o != null && this.IsKey == o.IsKey && this.Identifier.DoMatch(o.Identifier, match) && this.Expression.DoMatch(o.Expression, match); } } public class ConditionalExpression : Expression { public readonly static Role ConditionExpressionRole = new Role("ConditionExpressionRole", Expression.Null); public readonly static Role TrueExpressionRole = new Role("TrueExpressionRole", Expression.Null); public readonly static Role FalseExpressionRole = new Role("FalseExpressionRole", Expression.Null); public VBTokenNode IfToken { get { return GetChildByRole (Roles.Keyword); } } public Expression ConditionExpression { get { return GetChildByRole (ConditionExpressionRole); } set { SetChildByRole (ConditionExpressionRole, value); } } public Expression TrueExpression { get { return GetChildByRole (TrueExpressionRole); } set { SetChildByRole (TrueExpressionRole, value); } } public Expression FalseExpression { get { return GetChildByRole (FalseExpressionRole); } set { SetChildByRole (FalseExpressionRole, value); } } protected internal override bool DoMatch(AstNode other, ICSharpCode.NRefactory.PatternMatching.Match match) { throw new NotImplementedException(); } public override S AcceptVisitor(IAstVisitor visitor, T data) { return visitor.VisitConditionalExpression(this, data); } } }