protected BinaryOperatorExpression(IExpression leftOprand, IExpression rightOprand, ExpressionPrecedence precedence, bool leftCombine) { this.LeftOprand = leftOprand; this.RightOprand = rightOprand; this.Precedence = precedence; this.LeftCombine = leftCombine; }
public UnaryOperatorExpression(IExpression operand, ExpressionPrecedence precedence) { if (operand == null) { throw new ArgumentNullException("operand"); } this.Operand = operand; this.Precedence = precedence; }
/// <summary> /// Reads a conditional logical expression. /// </summary> /// <param name="parentProxy">Represents the parent item.</param> /// <param name="leftHandSide">The expression on the left hand side of the operator.</param> /// <param name="previousPrecedence">The precedence of the expression just before this one.</param> /// <returns>Returns the expression.</returns> private ConditionalLogicalExpression GetConditionalPreprocessorAndOrExpression( CodeUnitProxy parentProxy, Expression leftHandSide, ExpressionPrecedence previousPrecedence) { Param.AssertNotNull(parentProxy, "parentProxy"); Param.AssertNotNull(leftHandSide, "leftHandSide"); Param.Ignore(previousPrecedence); ConditionalLogicalExpression expression = null; this.AdvanceToNextConditionalDirectiveCodeSymbol(parentProxy); var expressionProxy = new CodeUnitProxy(this.document); // Create the operator symbol. OperatorSymbolToken operatorToken = this.PeekOperatorSymbolToken(); // Check the precedence of the operators to make sure we can gather this statement now. ExpressionPrecedence precedence = GetOperatorPrecedence(operatorToken.SymbolType); if (CheckPrecedence(previousPrecedence, precedence)) { // Add the operator token to the document and advance the symbol manager up to it. this.symbols.Advance(); expressionProxy.Children.Add(operatorToken); // Get the expression on the right-hand side of the operator. Expression rightHandSide = this.GetNextConditionalPreprocessorExpression(this.document, expressionProxy, precedence); if (rightHandSide == null) { throw new SyntaxException(this.document, operatorToken.LineNumber); } // Get the expression operator type. switch (operatorToken.SymbolType) { case OperatorType.ConditionalAnd: expression = new ConditionalAndExpression(expressionProxy, leftHandSide, rightHandSide); break; case OperatorType.ConditionalOr: expression = new ConditionalOrExpression(expressionProxy, leftHandSide, rightHandSide); break; default: throw new SyntaxException(this.document, operatorToken.LineNumber); } parentProxy.Children.Add(expression); } return(expression); }
/// <summary> /// Determines the operator precedence of the token. /// </summary> /// <param name="value"></param> private void DeterminePrecedence(string value) { if (value.Equals("+", StringComparison.InvariantCultureIgnoreCase)) { _precedence = ExpressionPrecedence.Add; } else if (value.Equals("-", StringComparison.InvariantCultureIgnoreCase)) { _precedence = ExpressionPrecedence.Subtract; } else if (value.Equals("*", StringComparison.InvariantCultureIgnoreCase)) { _precedence = ExpressionPrecedence.MultiplyOrDivide; } else if (value.Equals("/", StringComparison.InvariantCultureIgnoreCase)) { _precedence = ExpressionPrecedence.MultiplyOrDivide; } }
/// <summary> /// Determine the actual operation precedence for this operation. /// </summary> /// <param name="operation"></param> /// <returns></returns> private static ExpressionPrecedence DeterminePrecedence(Token operation) { ExpressionPrecedence precedence = ExpressionPrecedence.Null; if (operation.ToString().Equals("+", StringComparison.InvariantCultureIgnoreCase)) { precedence = ExpressionPrecedence.Add; } else if (operation.ToString().Equals("-", StringComparison.InvariantCultureIgnoreCase)) { precedence = ExpressionPrecedence.Subtract; } else if (operation.ToString().Equals("*", StringComparison.InvariantCultureIgnoreCase)) { precedence = ExpressionPrecedence.MultiplyOrDivide; } else if (operation.ToString().Equals("/", StringComparison.InvariantCultureIgnoreCase)) { precedence = ExpressionPrecedence.MultiplyOrDivide; } return(precedence); }
protected ArithmeticBinaryOperatorExpression(IExpression leftOprand, IExpression rightOprand, ExpressionPrecedence precedence) : base(leftOprand, rightOprand, precedence) { }
/// <summary> /// Given an expression, reads further to see if it is actually a sub-expression within a larger expression. /// </summary> /// <param name="sourceCode"> /// The source code. /// </param> /// <param name="parentReference"> /// The parent code part. /// </param> /// <param name="leftSide"> /// The known expression which might have an extension. /// </param> /// <param name="previousPrecedence"> /// The precedence of the expression just before this one. /// </param> /// <returns> /// Returns the expression. /// </returns> private Expression GetConditionalPreprocessorExpressionExtension( SourceCode sourceCode, Reference<ICodePart> parentReference, Expression leftSide, ExpressionPrecedence previousPrecedence) { Param.AssertNotNull(sourceCode, "sourceCode"); Param.AssertNotNull(parentReference, "parentReference"); Param.AssertNotNull(leftSide, "leftSide"); Param.Ignore(previousPrecedence); // The expression to return. Expression expression = null; // Move past whitespace. this.AdvanceToNextConditionalDirectiveCodeSymbol(parentReference); Symbol symbol = this.symbols.Peek(1); if (symbol != null) { // Check the type of the next symbol. if (symbol.SymbolType != SymbolType.CloseParenthesis) { // Check whether this is an operator symbol. OperatorType type; OperatorCategory category; if (GetOperatorType(symbol, out type, out category)) { switch (type) { case OperatorType.ConditionalEquals: case OperatorType.NotEquals: expression = this.GetConditionalPreprocessorEqualityExpression(sourceCode, parentReference, leftSide, previousPrecedence); break; case OperatorType.ConditionalAnd: case OperatorType.ConditionalOr: expression = this.GetConditionalPreprocessorAndOrExpression(sourceCode, parentReference, leftSide, previousPrecedence); break; } } } } return expression; }
/// <summary> /// Reads a conditional logical expression. /// </summary> /// <param name="leftHandSide">The expression on the left hand side of the operator.</param> /// <param name="previousPrecedence">The precedence of the expression just before this one.</param> /// <param name="unsafeCode">Indicates whether the code being parsed resides in an unsafe code block.</param> /// <returns>Returns the expression.</returns> private ConditionalLogicalExpression GetConditionalLogicalExpression( Expression leftHandSide, ExpressionPrecedence previousPrecedence, bool unsafeCode) { Param.AssertNotNull(leftHandSide, "leftHandSide"); Param.Ignore(previousPrecedence); Param.Ignore(unsafeCode); ConditionalLogicalExpression expression = null; // Read the details of the expression. OperatorSymbol operatorToken = this.PeekOperatorToken(); Debug.Assert(operatorToken.Category == OperatorCategory.Logical, "Expected a logical operator"); // Check the precedence of the operators to make sure we can gather this statement now. ExpressionPrecedence precedence = this.GetOperatorPrecedence(operatorToken.SymbolType); if (this.CheckPrecedence(previousPrecedence, precedence)) { // Add the operator token to the document and advance the symbol manager up to it. this.symbols.Advance(); this.tokens.Add(operatorToken); // Get the expression on the right-hand side of the operator. Expression rightHandSide = this.GetOperatorRightHandExpression(precedence, unsafeCode); // Create the partial token list for the expression. CsTokenList partialTokens = new CsTokenList(this.tokens, leftHandSide.Tokens.First, this.tokens.Last); // Get the expression operator type. ConditionalLogicalExpression.Operator type; switch (operatorToken.SymbolType) { case OperatorType.ConditionalAnd: type = ConditionalLogicalExpression.Operator.And; break; case OperatorType.ConditionalOr: type = ConditionalLogicalExpression.Operator.Or; break; default: Debug.Fail("Unexpected operator type"); throw new InvalidOperationException(); } // Create and return the expression. expression = new ConditionalLogicalExpression(partialTokens, type, leftHandSide, rightHandSide); } return expression; }
private bool IsCastExpression(ExpressionPrecedence previousPrecedence, bool unsafeCode) { Param.Ignore(previousPrecedence); Param.Ignore(unsafeCode); bool cast = false; // The first symbol must be an opening parenthesis. int index = this.GetNextCodeSymbolIndex(1); if (index != -1) { Symbol symbol = this.symbols.Peek(index); if (symbol.SymbolType == SymbolType.OpenParenthesis) { // The inner expression must have a type signature. if (this.HasTypeSignature(index + 1, unsafeCode, out index)) { if (index != -1) { symbol = this.symbols.Peek(index); if (symbol.SymbolType == SymbolType.Other) { index = this.AdvanceToEndOfName(index); } // The next character must be a closing parenthesis or this is not a cast. if (index != -1) { index = this.GetNextCodeSymbolIndex(index + 1); if (index != -1) { symbol = this.symbols.Peek(index); if (symbol.SymbolType == SymbolType.CloseParenthesis) { // This looks like it might be a cast, but a cast can only appear in front // of the following types of symbols. index = this.GetNextCodeSymbolIndex(index + 1); if (index != -1) { Symbol nextSymbol = this.symbols.Peek(index); SymbolType symbolType = nextSymbol.SymbolType; if (symbolType == SymbolType.Other) { // This could be an expression like: // from type in x where (type.IsClass) select type; if (previousPrecedence != ExpressionPrecedence.Query || (nextSymbol.Text != "where" && nextSymbol.Text != "select" && nextSymbol.Text != "group" && nextSymbol.Text != "into" && nextSymbol.Text != "orderby" && nextSymbol.Text != "join" && nextSymbol.Text != "let" && nextSymbol.Text != "equals" && nextSymbol.Text != "by" && nextSymbol.Text != "on")) { cast = true; } } else if (symbolType == SymbolType.OpenParenthesis || symbolType == SymbolType.Number || symbolType == SymbolType.Tilde || symbolType == SymbolType.Not || symbolType == SymbolType.New || symbolType == SymbolType.Sizeof || symbolType == SymbolType.Typeof || symbolType == SymbolType.Default || symbolType == SymbolType.Checked || symbolType == SymbolType.Unchecked || symbolType == SymbolType.This || symbolType == SymbolType.Base || symbolType == SymbolType.Null || symbolType == SymbolType.True || symbolType == SymbolType.False || symbolType == SymbolType.Plus || symbolType == SymbolType.Minus || symbolType == SymbolType.String || symbolType == SymbolType.Delegate) { cast = true; } else if (symbolType == SymbolType.Increment || symbolType == SymbolType.Decrement) { // This could be a cast if the symbol following the cast is an "other" or an opening parenthesis. For instance: // object x = (object)++y; // object x = (object)++(y); // object x = (object)++this.y; // However this is not a cast when: // object x = (x)++; int next = this.GetNextCodeSymbolIndex(index + 1); if (next != -1) { SymbolType nextSymbolType = this.symbols.Peek(next).SymbolType; if (nextSymbolType == SymbolType.Other || nextSymbolType == SymbolType.This || nextSymbolType == SymbolType.Base || nextSymbolType == SymbolType.OpenParenthesis) { cast = true; } } } else if (symbolType == SymbolType.LogicalAnd && unsafeCode) { // For example: (IntPtr*)&rc.left cast = true; } } } } } } } } } return cast; }
/// <summary> /// Reads and returns the right-hand expression of an operator expression. /// </summary> /// <param name="precedence">The precendence of this operator expression.</param> /// <param name="parentReference">The parent code unit.</param> /// <param name="unsafeCode">Indicates whether the code being parsed resides in an unsafe code block.</param> /// <returns>Returns the expression.</returns> private Expression GetOperatorRightHandExpression(ExpressionPrecedence precedence, Reference<ICodePart> parentReference, bool unsafeCode) { Param.AssertNotNull(precedence, "precedence"); Param.AssertNotNull(parentReference, "parentReference"); Param.Ignore(unsafeCode); // Get the right hand expression. Expression rightHandSide = this.GetNextExpression(precedence, parentReference, unsafeCode); if (rightHandSide == null) { throw this.CreateSyntaxException(); } // Make sure the right hand side has at least one token. Debug.Assert(rightHandSide.Tokens.First != null, "The right-hand side should not be empty."); return rightHandSide; }
/// <summary> /// Reads the next expression from the file and returns it. /// </summary> /// <param name="previousPrecedence">The precedence of the expression just before this one.</param> /// <param name="parentReference">Reference to the parent code part.</param> /// <param name="unsafeCode">Indicates whether the code being parsed resides in an unsafe code block.</param> /// <returns>Returns the expression.</returns> private Expression GetNextExpression(ExpressionPrecedence previousPrecedence, Reference<ICodePart> parentReference, bool unsafeCode) { Param.Ignore(previousPrecedence); Param.AssertNotNull(parentReference, "parentReference"); Param.Ignore(unsafeCode); return this.GetNextExpression(previousPrecedence, parentReference, unsafeCode, false, false); }
protected BinaryOperatorExpression(IExpression leftOprand, IExpression rightOprand, ExpressionPrecedence precedence) : this(leftOprand, rightOprand, precedence, true) { }
/// <summary> /// Creates an instance of FunctionToken. /// </summary> /// <param name="other"></param> protected FunctionToken(Token other) : base(other) { _precedence = ExpressionPrecedence.Function; }
/// <summary> /// Creates an instance of FunctionToken. /// </summary> /// <param name="value"></param> protected FunctionToken(string value) : base(value) { _precedence = ExpressionPrecedence.Function; }
private Expression GetExpressionExtension( Expression leftSide, ExpressionPrecedence previousPrecedence, Reference<ICodePart> parentReference, bool unsafeCode, bool typeExpression, bool allowVariableDeclaration) { Param.AssertNotNull(leftSide, "leftSide"); Param.Ignore(previousPrecedence); Param.AssertNotNull(parentReference, "parentReference"); Param.Ignore(unsafeCode); Param.Ignore(typeExpression); Param.Ignore(allowVariableDeclaration); // The expression to return. Expression expression = null; Symbol symbol = this.GetNextSymbol(parentReference); if (typeExpression) { // A type expression can only be extended by a member access expression. if (symbol.SymbolType == SymbolType.Dot || symbol.SymbolType == SymbolType.QualifiedAlias) { expression = this.GetMemberAccessExpression(leftSide, previousPrecedence, unsafeCode); } } else { // Check the type of the next symbol. switch (symbol.SymbolType) { case SymbolType.CloseParenthesis: case SymbolType.CloseSquareBracket: case SymbolType.Semicolon: case SymbolType.Comma: break; case SymbolType.Dot: case SymbolType.QualifiedAlias: case SymbolType.Pointer: expression = this.GetMemberAccessExpression(leftSide, previousPrecedence, unsafeCode); break; case SymbolType.Other: // This can only be a variable declaration expression if the left // side expression is a simple Literal or a MemberAccess which represents the type. if (allowVariableDeclaration && (leftSide.ExpressionType == ExpressionType.Literal || leftSide.ExpressionType == ExpressionType.MemberAccess)) { expression = this.GetVariableDeclarationExpression(leftSide, previousPrecedence, unsafeCode); } break; case SymbolType.OpenParenthesis: expression = this.GetMethodInvocationExpression(leftSide, previousPrecedence, unsafeCode); break; case SymbolType.OpenSquareBracket: expression = this.GetArrayAccessExpression(leftSide, previousPrecedence, unsafeCode); break; case SymbolType.As: expression = this.GetAsExpression(leftSide, previousPrecedence, parentReference, unsafeCode); break; case SymbolType.Is: expression = this.GetIsExpression(leftSide, previousPrecedence, parentReference, unsafeCode); break; case SymbolType.Increment: expression = this.GetPrimaryIncrementExpression(leftSide, previousPrecedence); break; case SymbolType.Decrement: expression = this.GetPrimaryDecrementExpression(leftSide, previousPrecedence); break; default: // Check whether this is an operator symbol. OperatorType type; OperatorCategory category; if (GetOperatorType(symbol, out type, out category)) { switch (category) { case OperatorCategory.Conditional: // The question mark must come before the colon. if (type == OperatorType.ConditionalQuestionMark) { expression = this.GetConditionalExpression(leftSide, previousPrecedence, unsafeCode); } break; case OperatorCategory.Arithmetic: if (unsafeCode && type == OperatorType.Multiplication) { if (this.IsDereferenceExpression(leftSide)) { expression = this.GetUnsafeTypeExpression(leftSide, previousPrecedence, parentReference); } else { expression = this.GetArithmeticExpression(leftSide, previousPrecedence, parentReference, unsafeCode); } } else { expression = this.GetArithmeticExpression(leftSide, previousPrecedence, parentReference, unsafeCode); } break; case OperatorCategory.Shift: expression = this.GetArithmeticExpression(leftSide, previousPrecedence, parentReference, unsafeCode); break; case OperatorCategory.Assignment: expression = this.GetAssignmentExpression(leftSide, previousPrecedence, parentReference, unsafeCode); break; case OperatorCategory.Relational: // If this is a greater-than symbol, make sure it is not really a right-shift. if (type == OperatorType.GreaterThan) { // If the very next symbol is a greater-than or equals, then this is really a right-shift. Symbol next = this.symbols.Peek(2); if (next != null) { if (next.SymbolType == SymbolType.GreaterThanOrEquals) { // This is a right-shift-equals. this.symbols.Combine(1, 2, ">>=", SymbolType.RightShiftEquals); goto case OperatorCategory.Assignment; } else if (next.SymbolType == SymbolType.GreaterThan) { // This is a right-shift. this.symbols.Combine(1, 2, ">>", SymbolType.RightShift); goto case OperatorCategory.Shift; } } } expression = this.GetRelationalExpression(leftSide, previousPrecedence, parentReference, unsafeCode); break; case OperatorCategory.Logical: switch (type) { case OperatorType.LogicalAnd: case OperatorType.LogicalOr: case OperatorType.LogicalXor: expression = this.GetLogicalExpression(leftSide, previousPrecedence, parentReference, unsafeCode); break; case OperatorType.ConditionalAnd: case OperatorType.ConditionalOr: expression = this.GetConditionalLogicalExpression(leftSide, previousPrecedence, parentReference, unsafeCode); break; case OperatorType.NullCoalescingSymbol: expression = this.GetNullCoalescingExpression(leftSide, previousPrecedence, parentReference, unsafeCode); break; default: break; } break; } } break; } } return expression; }
/// <summary> /// Reads a member access expression. /// </summary> /// <param name="leftSide">The left side of the expression.</param> /// <param name="previousPrecedence">The precedence of the previous expression.</param> /// <param name="unsafeCode">Indicates whether the code is marked as unsafe.</param> /// <returns>Returns the expression.</returns> private MemberAccessExpression GetMemberAccessExpression( Expression leftSide, ExpressionPrecedence previousPrecedence, bool unsafeCode) { Param.AssertNotNull(leftSide, "leftSide"); Param.Ignore(previousPrecedence); Param.Ignore(unsafeCode); MemberAccessExpression expression = null; OperatorType operatorType; MemberAccessExpression.Operator expressionOperatorType; ExpressionPrecedence precedence; var expressionReference = new Reference<ICodePart>(); // The next symbol must one of the member access types. Symbol symbol = this.GetNextSymbol(expressionReference); if (symbol.SymbolType == SymbolType.Dot) { operatorType = OperatorType.MemberAccess; expressionOperatorType = MemberAccessExpression.Operator.Dot; precedence = ExpressionPrecedence.Primary; } else if (symbol.SymbolType == SymbolType.Pointer) { operatorType = OperatorType.Pointer; expressionOperatorType = MemberAccessExpression.Operator.Pointer; precedence = ExpressionPrecedence.Primary; } else if (symbol.SymbolType == SymbolType.QualifiedAlias) { operatorType = OperatorType.QualifiedAlias; expressionOperatorType = MemberAccessExpression.Operator.QualifiedAlias; precedence = ExpressionPrecedence.Global; } else { Debug.Fail("Unexpected operator type"); throw new InvalidOperationException(); } // Check the precedence. A member access has primary precedence. if (CheckPrecedence(previousPrecedence, precedence)) { // Add this to the document. this.tokens.Add(this.GetOperatorToken(operatorType, expressionReference)); // Get the member being accessed. This must be a literal. LiteralExpression member = this.GetLiteralExpression(expressionReference, unsafeCode); if (member == null) { throw this.CreateSyntaxException(); } // Create the token list. CsTokenList partialTokens = new CsTokenList(this.tokens, leftSide.Tokens.First, this.tokens.Last); // Create the expression. expression = new MemberAccessExpression(partialTokens, expressionOperatorType, leftSide, member); expressionReference.Target = expression; } return expression; }
/// <summary> /// Creates an instance of Expression. /// </summary> /// <param name="precedence"></param> /// <param name="operation"></param> /// <param name="operands"></param> protected Expression(ExpressionPrecedence precedence, Token operation, IList <Expression> operands) { _precedence = precedence; _operation = operation; _operands = operands; }
/// <summary> /// Reads a null coalescing expression. /// </summary> /// <param name="leftHandSide">The expression on the left hand side of the operator.</param> /// <param name="previousPrecedence">The precedence of the expression just before this one.</param> /// <param name="parentReference">The parent code unit.</param> /// <param name="unsafeCode">Indicates whether the code being parsed resides in an unsafe code block.</param> /// <returns>Returns the expression.</returns> private NullCoalescingExpression GetNullCoalescingExpression( Expression leftHandSide, ExpressionPrecedence previousPrecedence, Reference<ICodePart> parentReference, bool unsafeCode) { Param.AssertNotNull(leftHandSide, "leftHandSide"); Param.Ignore(previousPrecedence); Param.AssertNotNull(parentReference, "parentReference"); Param.Ignore(unsafeCode); NullCoalescingExpression expression = null; var expressionReference = new Reference<ICodePart>(); // Read the details of the expression. OperatorSymbol operatorToken = this.PeekOperatorToken(parentReference, expressionReference); Debug.Assert(operatorToken.SymbolType == OperatorType.NullCoalescingSymbol, "Expected a null-coalescing symbol"); // Check the precedence of the operators to make sure we can gather this statement now. ExpressionPrecedence precedence = GetOperatorPrecedence(operatorToken.SymbolType); if (CheckPrecedence(previousPrecedence, precedence)) { // Add the operator token to the document and advance the symbol manager up to it. this.symbols.Advance(); this.tokens.Add(operatorToken); // Get the expression on the right-hand side of the operator. Expression rightHandSide = this.GetOperatorRightHandExpression(precedence, expressionReference, unsafeCode); // Create the partial token list for the expression. CsTokenList partialTokens = new CsTokenList(this.tokens, leftHandSide.Tokens.First, this.tokens.Last); // Create and return the expression. expression = new NullCoalescingExpression(partialTokens, leftHandSide, rightHandSide); expressionReference.Target = expression; } return expression; }
/// <summary> /// Reads a relational expression. /// </summary> /// <param name="sourceCode"> /// The file containing the expression. /// </param> /// <param name="parentReference"> /// The parent code unit. /// </param> /// <param name="leftHandSide"> /// The expression on the left hand side of the operator. /// </param> /// <param name="previousPrecedence"> /// The precedence of the expression just before this one. /// </param> /// <returns> /// Returns the expression. /// </returns> private RelationalExpression GetConditionalPreprocessorEqualityExpression( SourceCode sourceCode, Reference <ICodePart> parentReference, Expression leftHandSide, ExpressionPrecedence previousPrecedence) { Param.AssertNotNull(sourceCode, "sourceCode"); Param.AssertNotNull(parentReference, "parentReference"); Param.AssertNotNull(leftHandSide, "leftHandSide"); Param.Ignore(previousPrecedence); RelationalExpression expression = null; this.AdvanceToNextConditionalDirectiveCodeSymbol(parentReference); Symbol firstSymbol = this.symbols.Peek(1); if (firstSymbol == null) { throw new SyntaxException(sourceCode, firstSymbol.LineNumber); } Reference <ICodePart> expressionReference = new Reference <ICodePart>(); // Create the operator symbol. OperatorType type; OperatorCategory category; GetOperatorType(firstSymbol, out type, out category); OperatorSymbol operatorToken = new OperatorSymbol(firstSymbol.Text, category, type, firstSymbol.Location, expressionReference, this.symbols.Generated); // Check the precedence of the operators to make sure we can gather this statement now. ExpressionPrecedence precedence = GetOperatorPrecedence(operatorToken.SymbolType); if (CheckPrecedence(previousPrecedence, precedence)) { // Add the operator token to the document and advance the symbol manager up to it. this.symbols.Advance(); this.tokens.Add(operatorToken); // Get the expression on the right-hand side of the operator. Expression rightHandSide = this.GetNextConditionalPreprocessorExpression(sourceCode, precedence); if (rightHandSide == null) { throw new SyntaxException(sourceCode, operatorToken.LineNumber); } // Create the partial token list for the expression. CsTokenList partialTokens = new CsTokenList(this.tokens, leftHandSide.Tokens.First, this.tokens.Last); // Get the expression operator type. RelationalExpression.Operator relationalType; switch (operatorToken.SymbolType) { case OperatorType.ConditionalEquals: relationalType = RelationalExpression.Operator.EqualTo; break; case OperatorType.NotEquals: relationalType = RelationalExpression.Operator.NotEqualTo; break; default: throw new SyntaxException(sourceCode, operatorToken.LineNumber); } // Create and return the expression. expression = new RelationalExpression(partialTokens, relationalType, leftHandSide, rightHandSide); expressionReference.Target = expression; } return(expression); }
/// <summary> /// Reads an unsafe type expression. /// </summary> /// <param name="type">The type expression.</param> /// <param name="previousPrecedence">The precedence of the previous expression.</param> /// <param name="parentReference">The parent code unit.</param> /// <returns>Returns the expression.</returns> private UnsafeAccessExpression GetUnsafeTypeExpression(Expression type, ExpressionPrecedence previousPrecedence, Reference<ICodePart> parentReference) { Param.Ignore(type); Param.AssertNotNull(previousPrecedence, "previousPrecedence"); Param.AssertNotNull(parentReference, "parentReference"); UnsafeAccessExpression expression = null; if (CheckPrecedence(previousPrecedence, ExpressionPrecedence.Unary)) { // Get the operator symbol. Symbol symbol = this.GetNextSymbol(parentReference); var expressionReference = new Reference<ICodePart>(); OperatorType operatorType; UnsafeAccessExpression.Operator unsafeOperatorType; if (symbol.SymbolType == SymbolType.LogicalAnd) { operatorType = OperatorType.AddressOf; unsafeOperatorType = UnsafeAccessExpression.Operator.AddressOf; } else if (symbol.SymbolType == SymbolType.Multiplication) { operatorType = OperatorType.Dereference; unsafeOperatorType = UnsafeAccessExpression.Operator.Dereference; } else { Debug.Fail("Unexpected operator type."); throw new InvalidOperationException(); } // Create a token for the operator symbol. this.symbols.Advance(); OperatorSymbol token = new OperatorSymbol( symbol.Text, OperatorCategory.Reference, operatorType, symbol.Location, expressionReference, this.symbols.Generated); this.tokens.Add(token); // Create the partial token list for the expression. CsTokenList partialTokens = new CsTokenList(this.tokens, type.Tokens.First, this.tokens.Last); // Create and return the expression. expression = new UnsafeAccessExpression(partialTokens, unsafeOperatorType, type); expressionReference.Target = expression; } return expression; }
/// <summary> /// Given an expression, reads further to see if it is actually a sub-expression within a larger expression. /// </summary> /// <param name="sourceCode"> /// The source code. /// </param> /// <param name="parentReference"> /// The parent code part. /// </param> /// <param name="leftSide"> /// The known expression which might have an extension. /// </param> /// <param name="previousPrecedence"> /// The precedence of the expression just before this one. /// </param> /// <returns> /// Returns the expression. /// </returns> private Expression GetConditionalPreprocessorExpressionExtension( SourceCode sourceCode, Reference <ICodePart> parentReference, Expression leftSide, ExpressionPrecedence previousPrecedence) { Param.AssertNotNull(sourceCode, "sourceCode"); Param.AssertNotNull(parentReference, "parentReference"); Param.AssertNotNull(leftSide, "leftSide"); Param.Ignore(previousPrecedence); // The expression to return. Expression expression = null; // Move past whitespace. this.AdvanceToNextConditionalDirectiveCodeSymbol(parentReference); Symbol symbol = this.symbols.Peek(1); if (symbol != null) { // Check the type of the next symbol. if (symbol.SymbolType != SymbolType.CloseParenthesis) { // Check whether this is an operator symbol. OperatorType type; OperatorCategory category; if (GetOperatorType(symbol, out type, out category)) { switch (type) { case OperatorType.ConditionalEquals: case OperatorType.NotEquals: expression = this.GetConditionalPreprocessorEqualityExpression(sourceCode, parentReference, leftSide, previousPrecedence); break; case OperatorType.ConditionalAnd: case OperatorType.ConditionalOr: expression = this.GetConditionalPreprocessorAndOrExpression(sourceCode, parentReference, leftSide, previousPrecedence); break; } } } } return(expression); }
/// <summary> /// Reads an as expression. /// </summary> /// <param name="leftHandSide">The expression on the left hand side of the operator.</param> /// <param name="previousPrecedence">The precedence of the expression just before this one.</param> /// <param name="parentReference">The parent code unit.</param> /// <param name="unsafeCode">Indicates whether the code being parsed resides in an unsafe code block.</param> /// <returns>Returns the expression.</returns> private AsExpression GetAsExpression( Expression leftHandSide, ExpressionPrecedence previousPrecedence, Reference<ICodePart> parentReference, bool unsafeCode) { Param.AssertNotNull(leftHandSide, "leftHandSide"); Param.Ignore(previousPrecedence); Param.AssertNotNull(parentReference, "parentReference"); Param.Ignore(unsafeCode); AsExpression expression = null; // Check the previous precedence to see if we are allowed to gather up the as expression. if (CheckPrecedence(previousPrecedence, ExpressionPrecedence.Relational)) { var expressionReference = new Reference<ICodePart>(); // Make sure the left hand side has at least one token. Debug.Assert(leftHandSide.Tokens.First != null, "The left hand side should not be empty"); // Get the as symbol. this.tokens.Add(this.GetToken(CsTokenType.As, SymbolType.As, parentReference, expressionReference)); // The next token must be the type. this.GetNextSymbol(SymbolType.Other, expressionReference); // Get the expression representing the type. LiteralExpression rightHandSide = this.GetTypeTokenExpression(expressionReference, unsafeCode, true); if (rightHandSide == null || rightHandSide.Tokens.First == null) { throw this.CreateSyntaxException(); } // Create the partial token list for the expression. CsTokenList partialTokens = new CsTokenList(this.tokens, leftHandSide.Tokens.First, this.tokens.Last); // Create and return the expression. expression = new AsExpression(partialTokens, leftHandSide, rightHandSide); expressionReference.Target = expression; } return expression; }
/// <summary> /// Reads the next expression from a conditional preprocessor directive. /// </summary> /// <param name="sourceCode"> /// The source code. /// </param> /// <param name="previousPrecedence"> /// The precedence of the expression just before this one. /// </param> /// <returns> /// Returns the expression. /// </returns> private Expression GetNextConditionalPreprocessorExpression(SourceCode sourceCode, ExpressionPrecedence previousPrecedence) { Param.AssertNotNull(sourceCode, "sourceCode"); Param.Ignore(previousPrecedence); Reference <ICodePart> parentReference = new Reference <ICodePart>(); // Move past comments and whitepace. this.AdvanceToNextConditionalDirectiveCodeSymbol(parentReference); // Saves the next expression. Expression expression = null; // Get the next symbol. Symbol symbol = this.symbols.Peek(1); if (symbol != null) { switch (symbol.SymbolType) { case SymbolType.Other: expression = this.GetConditionalPreprocessorConstantExpression(); break; case SymbolType.Not: expression = this.GetConditionalPreprocessorNotExpression(sourceCode, parentReference); break; case SymbolType.OpenParenthesis: expression = this.GetConditionalPreprocessorParenthesizedExpression(sourceCode, parentReference); break; case SymbolType.False: this.symbols.Advance(); Reference <ICodePart> falseExpressionReference = new Reference <ICodePart>(); CsToken token = new CsToken(symbol.Text, CsTokenType.False, symbol.Location, falseExpressionReference, this.symbols.Generated); Node <CsToken> tokenNode = this.tokens.InsertLast(token); expression = new LiteralExpression(new CsTokenList(this.tokens, tokenNode, tokenNode), tokenNode); falseExpressionReference.Target = expression; break; case SymbolType.True: this.symbols.Advance(); Reference <ICodePart> trueExpressionReference = new Reference <ICodePart>(); token = new CsToken(symbol.Text, CsTokenType.True, symbol.Location, trueExpressionReference, this.symbols.Generated); tokenNode = this.tokens.InsertLast(token); expression = new LiteralExpression(new CsTokenList(this.tokens, tokenNode, tokenNode), tokenNode); trueExpressionReference.Target = expression; break; default: throw new SyntaxException(sourceCode, symbol.LineNumber); } } // Gather up all extensions to this expression. while (expression != null) { Reference <ICodePart> expressionReference = new Reference <ICodePart>(expression); // Check if there is an extension to this expression. Expression extension = this.GetConditionalPreprocessorExpressionExtension(sourceCode, expressionReference, expression, previousPrecedence); if (extension != null) { // The larger expression is what we want to return here. expression = extension; } else { // There are no more extensions. break; } } // Return the expression. return(expression); }
/// <summary> /// Reads an arithmetic expression. /// </summary> /// <param name="leftHandSide">The expression on the left hand side of the operator.</param> /// <param name="previousPrecedence">The precedence of the expression just before this one.</param> /// <param name="unsafeCode">Indicates whether the code being parsed resides in an unsafe code block.</param> /// <returns>Returns the expression.</returns> private ArithmeticExpression GetArithmeticExpression( Expression leftHandSide, ExpressionPrecedence previousPrecedence, bool unsafeCode) { Param.AssertNotNull(leftHandSide, "leftHandSide"); Param.Ignore(previousPrecedence); Param.Ignore(unsafeCode); ArithmeticExpression expression = null; // Read the details of the expression. OperatorSymbol operatorToken = this.PeekOperatorToken(); Debug.Assert( operatorToken.Category == OperatorCategory.Arithmetic || operatorToken.Category == OperatorCategory.Shift, "Expected an arithmetic or shift operator"); // Check the precedence of the operators to make sure we can gather this statement now. ExpressionPrecedence precedence = this.GetOperatorPrecedence(operatorToken.SymbolType); if (this.CheckPrecedence(previousPrecedence, precedence)) { // Add the operator token to the document and advance the symbol manager up to it. this.symbols.Advance(); this.tokens.Add(operatorToken); // Get the expression on the right-hand side of the operator. Expression rightHandSide = this.GetOperatorRightHandExpression(precedence, unsafeCode); // Create the partial token list for the expression. CsTokenList partialTokens = new CsTokenList(this.tokens, leftHandSide.Tokens.First, this.tokens.Last); // Get the expression operator type. ArithmeticExpression.Operator type; switch (operatorToken.SymbolType) { case OperatorType.Plus: type = ArithmeticExpression.Operator.Addition; break; case OperatorType.Minus: type = ArithmeticExpression.Operator.Subtraction; break; case OperatorType.Multiplication: type = ArithmeticExpression.Operator.Multiplication; break; case OperatorType.Division: type = ArithmeticExpression.Operator.Division; break; case OperatorType.Mod: type = ArithmeticExpression.Operator.Mod; break; case OperatorType.LeftShift: type = ArithmeticExpression.Operator.LeftShift; break; case OperatorType.RightShift: type = ArithmeticExpression.Operator.RightShift; break; default: Debug.Fail("Unexpected operator type"); throw new InvalidOperationException(); } // Create and return the expression. expression = new ArithmeticExpression(partialTokens, type, leftHandSide, rightHandSide); } return expression; }
public PolyadicOperatorExpression(ExpressionPrecedence precedence) : this(precedence, true) { }
/// <summary> /// Reads a relational expression. /// </summary> /// <param name="sourceCode"> /// The file containing the expression. /// </param> /// <param name="parentReference"> /// The parent code unit. /// </param> /// <param name="leftHandSide"> /// The expression on the left hand side of the operator. /// </param> /// <param name="previousPrecedence"> /// The precedence of the expression just before this one. /// </param> /// <returns> /// Returns the expression. /// </returns> private RelationalExpression GetConditionalPreprocessorEqualityExpression( SourceCode sourceCode, Reference<ICodePart> parentReference, Expression leftHandSide, ExpressionPrecedence previousPrecedence) { Param.AssertNotNull(sourceCode, "sourceCode"); Param.AssertNotNull(parentReference, "parentReference"); Param.AssertNotNull(leftHandSide, "leftHandSide"); Param.Ignore(previousPrecedence); RelationalExpression expression = null; this.AdvanceToNextConditionalDirectiveCodeSymbol(parentReference); Symbol firstSymbol = this.symbols.Peek(1); if (firstSymbol == null) { throw new SyntaxException(sourceCode, firstSymbol.LineNumber); } Reference<ICodePart> expressionReference = new Reference<ICodePart>(); // Create the operator symbol. OperatorType type; OperatorCategory category; GetOperatorType(firstSymbol, out type, out category); OperatorSymbol operatorToken = new OperatorSymbol(firstSymbol.Text, category, type, firstSymbol.Location, expressionReference, this.symbols.Generated); // Check the precedence of the operators to make sure we can gather this statement now. ExpressionPrecedence precedence = GetOperatorPrecedence(operatorToken.SymbolType); if (CheckPrecedence(previousPrecedence, precedence)) { // Add the operator token to the document and advance the symbol manager up to it. this.symbols.Advance(); this.tokens.Add(operatorToken); // Get the expression on the right-hand side of the operator. Expression rightHandSide = this.GetNextConditionalPreprocessorExpression(sourceCode, precedence); if (rightHandSide == null) { throw new SyntaxException(sourceCode, operatorToken.LineNumber); } // Create the partial token list for the expression. CsTokenList partialTokens = new CsTokenList(this.tokens, leftHandSide.Tokens.First, this.tokens.Last); // Get the expression operator type. RelationalExpression.Operator relationalType; switch (operatorToken.SymbolType) { case OperatorType.ConditionalEquals: relationalType = RelationalExpression.Operator.EqualTo; break; case OperatorType.NotEquals: relationalType = RelationalExpression.Operator.NotEqualTo; break; default: throw new SyntaxException(sourceCode, operatorToken.LineNumber); } // Create and return the expression. expression = new RelationalExpression(partialTokens, relationalType, leftHandSide, rightHandSide); expressionReference.Target = expression; } return expression; }
public PolyadicOperatorExpression(ExpressionPrecedence precedence, bool leftCombine) : this(precedence, 4) { }
/// <summary> /// Reads the next expression from a conditional preprocessor directive. /// </summary> /// <param name="sourceCode"> /// The source code. /// </param> /// <param name="previousPrecedence"> /// The precedence of the expression just before this one. /// </param> /// <returns> /// Returns the expression. /// </returns> private Expression GetNextConditionalPreprocessorExpression(SourceCode sourceCode, ExpressionPrecedence previousPrecedence) { Param.AssertNotNull(sourceCode, "sourceCode"); Param.Ignore(previousPrecedence); Reference<ICodePart> parentReference = new Reference<ICodePart>(); // Move past comments and whitepace. this.AdvanceToNextConditionalDirectiveCodeSymbol(parentReference); // Saves the next expression. Expression expression = null; // Get the next symbol. Symbol symbol = this.symbols.Peek(1); if (symbol != null) { switch (symbol.SymbolType) { case SymbolType.Other: expression = this.GetConditionalPreprocessorConstantExpression(); break; case SymbolType.Not: expression = this.GetConditionalPreprocessorNotExpression(sourceCode, parentReference); break; case SymbolType.OpenParenthesis: expression = this.GetConditionalPreprocessorParenthesizedExpression(sourceCode, parentReference); break; case SymbolType.False: this.symbols.Advance(); Reference<ICodePart> falseExpressionReference = new Reference<ICodePart>(); CsToken token = new CsToken(symbol.Text, CsTokenType.False, symbol.Location, falseExpressionReference, this.symbols.Generated); Node<CsToken> tokenNode = this.tokens.InsertLast(token); expression = new LiteralExpression(new CsTokenList(this.tokens, tokenNode, tokenNode), tokenNode); falseExpressionReference.Target = expression; break; case SymbolType.True: this.symbols.Advance(); Reference<ICodePart> trueExpressionReference = new Reference<ICodePart>(); token = new CsToken(symbol.Text, CsTokenType.True, symbol.Location, trueExpressionReference, this.symbols.Generated); tokenNode = this.tokens.InsertLast(token); expression = new LiteralExpression(new CsTokenList(this.tokens, tokenNode, tokenNode), tokenNode); trueExpressionReference.Target = expression; break; default: throw new SyntaxException(sourceCode, symbol.LineNumber); } } // Gather up all extensions to this expression. while (expression != null) { Reference<ICodePart> expressionReference = new Reference<ICodePart>(expression); // Check if there is an extension to this expression. Expression extension = this.GetConditionalPreprocessorExpressionExtension(sourceCode, expressionReference, expression, previousPrecedence); if (extension != null) { // The larger expression is what we want to return here. expression = extension; } else { // There are no more extensions. break; } } // Return the expression. return expression; }
public PolyadicOperatorExpression(ExpressionPrecedence precedence, int initArity) { this.precedence = precedence; this.operands = new List <IExpression>(initArity); }
/// <summary> /// Reads a conditional expression. /// </summary> /// <param name="leftHandSide">The expression on the left hand side of the operator.</param> /// <param name="previousPrecedence">The precedence of the expression just before this one.</param> /// <param name="unsafeCode">Indicates whether the code being parsed resides in an unsafe code block.</param> /// <returns>Returns the expression.</returns> private ConditionalExpression GetConditionalExpression( Expression leftHandSide, ExpressionPrecedence previousPrecedence, bool unsafeCode) { Param.AssertNotNull(leftHandSide, "leftHandSide"); Param.Ignore(unsafeCode); Param.Ignore(previousPrecedence); ConditionalExpression expression = null; if (CheckPrecedence(previousPrecedence, ExpressionPrecedence.Conditional)) { var expressionReference = new Reference<ICodePart>(); // Get the first operator. this.tokens.Add(this.GetOperatorToken(OperatorType.ConditionalQuestionMark, expressionReference)); // Get the expression on the right-hand side of the operator. Expression trueValue = this.GetOperatorRightHandExpression(ExpressionPrecedence.Conditional, expressionReference, unsafeCode); // Get the next operator and make sure it is the correct type. this.tokens.Add(this.GetOperatorToken(OperatorType.ConditionalColon, expressionReference)); // Get the expression on the right-hand side of the operator. Expression falseValue = this.GetOperatorRightHandExpression(ExpressionPrecedence.None, expressionReference, unsafeCode); // Create the partial token list for the expression. CsTokenList partialTokens = new CsTokenList(this.tokens, leftHandSide.Tokens.First, this.tokens.Last); // Create and return the expression. expression = new ConditionalExpression(partialTokens, leftHandSide, trueValue, falseValue); expressionReference.Target = expression; } return expression; }
private NullCoalescingExpression GetNullCoalescingExpression(Expression leftHandSide, ExpressionPrecedence previousPrecedence, bool unsafeCode) { NullCoalescingExpression expression = null; OperatorSymbol item = this.PeekOperatorToken(); ExpressionPrecedence operatorPrecedence = GetOperatorPrecedence(item.SymbolType); if (CheckPrecedence(previousPrecedence, operatorPrecedence)) { this.symbols.Advance(); this.tokens.Add(item); Expression operatorRightHandExpression = this.GetOperatorRightHandExpression(operatorPrecedence, unsafeCode); CsTokenList tokens = new CsTokenList(this.tokens, leftHandSide.Tokens.First, this.tokens.Last); expression = new NullCoalescingExpression(tokens, leftHandSide, operatorRightHandExpression); } return expression; }
/// <summary> /// Compares the precendence of the previous expression with the precedence of the next expression, /// to determine which has the higher precedence value. /// </summary> /// <param name="previousPrecedence">The previous expression's precedence.</param> /// <param name="nextPrecedence">The next expression's precendence.</param> /// <returns>Returns true if the next expression has greater precedence than the next expression.</returns> private static bool CheckPrecedence(ExpressionPrecedence previousPrecedence, ExpressionPrecedence nextPrecedence) { Param.AssertNotNull(previousPrecedence, "previousPrecedence"); Param.AssertNotNull(nextPrecedence, "nextPrecedence"); // Two expressions with no precendence can be chained back to back, and conditional expressions // are allowed to be embedded within other conditional expressions. if ((previousPrecedence == ExpressionPrecedence.None && nextPrecedence == ExpressionPrecedence.None) || (previousPrecedence == ExpressionPrecedence.Conditional && nextPrecedence == ExpressionPrecedence.Conditional)) { return true; } return (int)previousPrecedence > (int)nextPrecedence; }
private Expression GetOperatorRightHandExpression(ExpressionPrecedence precedence, bool unsafeCode) { Expression nextExpression = this.GetNextExpression(precedence, unsafeCode); if (nextExpression == null) { throw this.CreateSyntaxException(); } return nextExpression; }
/// <summary> /// Reads a method access expression. /// </summary> /// <param name="methodName">The name of the method being called.</param> /// <param name="previousPrecedence">The precedence of the previous expression.</param> /// <param name="unsafeCode">Indicates whether the code being parsed resides in an unsafe code block.</param> /// <returns>Returns the expression.</returns> private MethodInvocationExpression GetMethodInvocationExpression( Expression methodName, ExpressionPrecedence previousPrecedence, bool unsafeCode) { Param.AssertNotNull(methodName, "methodName"); Param.Ignore(previousPrecedence); Param.Ignore(unsafeCode); MethodInvocationExpression expression = null; if (CheckPrecedence(previousPrecedence, ExpressionPrecedence.Primary)) { var expressionReference = new Reference<ICodePart>(); // The next symbol will be the opening parenthesis. Bracket openParenthesis = this.GetBracketToken(CsTokenType.OpenParenthesis, SymbolType.OpenParenthesis, expressionReference); Node<CsToken> openParenthesisNode = this.tokens.InsertLast(openParenthesis); // Get the argument list now. IList<Argument> argumentList = this.GetArgumentList(SymbolType.CloseParenthesis, expressionReference, unsafeCode); // Get the closing parenthesis. Bracket closeParenthesis = this.GetBracketToken(CsTokenType.CloseParenthesis, SymbolType.CloseParenthesis, expressionReference); Node<CsToken> closeParenthesisNode = this.tokens.InsertLast(closeParenthesis); openParenthesis.MatchingBracketNode = closeParenthesisNode; closeParenthesis.MatchingBracketNode = openParenthesisNode; // Pull out the first token from the method name. Debug.Assert(methodName.Tokens.First != null, "The method name should not be empty"); Node<CsToken> firstTokenNode = methodName.Tokens.First; // Create the token list for the method invocation expression. CsTokenList partialTokens = new CsTokenList(this.tokens, firstTokenNode, this.tokens.Last); // Create and return the expression. expression = new MethodInvocationExpression(partialTokens, methodName, argumentList); expressionReference.Target = expression; } return expression; }
private IncrementExpression GetPrimaryIncrementExpression(Expression leftHandSide, ExpressionPrecedence previousPrecedence) { IncrementExpression expression = null; if (CheckPrecedence(previousPrecedence, ExpressionPrecedence.Primary)) { this.tokens.Add(this.GetOperatorToken(OperatorType.Increment)); CsTokenList tokens = new CsTokenList(this.tokens, leftHandSide.Tokens.First, this.tokens.Last); expression = new IncrementExpression(tokens, leftHandSide, IncrementExpression.IncrementType.Postfix); } return expression; }
private Expression GetNextExpression( ExpressionPrecedence previousPrecedence, Reference<ICodePart> parentReference, bool unsafeCode, bool allowVariableDeclaration, bool typeExpression) { Param.Ignore(previousPrecedence); Param.AssertNotNull(parentReference, "parentReference"); Param.Ignore(unsafeCode); Param.Ignore(allowVariableDeclaration); Param.Ignore(typeExpression); // Saves the next expression. Expression expression = null; // Get the next symbol. Symbol symbol = this.GetNextSymbol(parentReference); if (symbol != null) { switch (symbol.SymbolType) { case SymbolType.Other: if (this.IsLambdaExpression()) { expression = this.GetLambdaExpression(parentReference, unsafeCode); } else if (this.IsQueryExpression(unsafeCode)) { expression = this.GetQueryExpression(parentReference, unsafeCode); } // If the expression is still null now, this is just a regular 'other' expression. if (expression == null) { expression = this.GetOtherExpression(parentReference, allowVariableDeclaration, unsafeCode); } break; case SymbolType.Checked: expression = this.GetCheckedExpression(parentReference, unsafeCode); break; case SymbolType.Unchecked: expression = this.GetUncheckedExpression(parentReference, unsafeCode); break; case SymbolType.New: expression = this.GetNewAllocationExpression(parentReference, unsafeCode); break; case SymbolType.Stackalloc: expression = this.GetStackallocExpression(parentReference, unsafeCode); break; case SymbolType.Sizeof: expression = this.GetSizeofExpression(parentReference, unsafeCode); break; case SymbolType.Typeof: expression = this.GetTypeofExpression(parentReference, unsafeCode); break; case SymbolType.Default: expression = this.GetDefaultValueExpression(parentReference, unsafeCode); break; case SymbolType.Delegate: expression = this.GetAnonymousMethodExpression(parentReference, unsafeCode); break; case SymbolType.Increment: if (this.IsUnaryExpression()) { expression = this.GetUnaryIncrementExpression(unsafeCode); } break; case SymbolType.Decrement: if (this.IsUnaryExpression()) { expression = this.GetUnaryDecrementExpression(unsafeCode); } break; case SymbolType.Plus: case SymbolType.Minus: if (this.IsUnaryExpression()) { expression = this.GetUnaryExpression(parentReference, unsafeCode); } break; case SymbolType.Not: case SymbolType.Tilde: expression = this.GetUnaryExpression(parentReference, unsafeCode); break; case SymbolType.OpenParenthesis: if (this.IsLambdaExpression()) { expression = this.GetLambdaExpression(parentReference, unsafeCode); } else { expression = this.GetOpenParenthesisExpression(previousPrecedence, unsafeCode); } break; case SymbolType.Number: var numberExpressionReference = new Reference<ICodePart>(); Node<CsToken> tokenNode = this.tokens.InsertLast(this.GetToken(CsTokenType.Number, SymbolType.Number, numberExpressionReference)); expression = new LiteralExpression(new CsTokenList(this.tokens, tokenNode, tokenNode), tokenNode); numberExpressionReference.Target = expression; break; case SymbolType.String: var stringExpressionReference = new Reference<ICodePart>(); tokenNode = this.tokens.InsertLast(this.GetToken(CsTokenType.String, SymbolType.String, stringExpressionReference)); expression = new LiteralExpression(new CsTokenList(this.tokens, tokenNode, tokenNode), tokenNode); stringExpressionReference.Target = expression; break; case SymbolType.True: var trueExpressionReference = new Reference<ICodePart>(); tokenNode = this.tokens.InsertLast(this.GetToken(CsTokenType.True, SymbolType.True, trueExpressionReference)); expression = new LiteralExpression(new CsTokenList(this.tokens, tokenNode, tokenNode), tokenNode); trueExpressionReference.Target = expression; break; case SymbolType.False: var falseExpressionReference = new Reference<ICodePart>(); tokenNode = this.tokens.InsertLast(this.GetToken(CsTokenType.False, SymbolType.False, falseExpressionReference)); expression = new LiteralExpression(new CsTokenList(this.tokens, tokenNode, tokenNode), tokenNode); falseExpressionReference.Target = expression; break; case SymbolType.Null: var nullExpressionReference = new Reference<ICodePart>(); tokenNode = this.tokens.InsertLast(this.GetToken(CsTokenType.Null, SymbolType.Null, nullExpressionReference)); expression = new LiteralExpression(new CsTokenList(this.tokens, tokenNode, tokenNode), tokenNode); nullExpressionReference.Target = expression; break; case SymbolType.This: var thisExpressionReference = new Reference<ICodePart>(); tokenNode = this.tokens.InsertLast(this.GetToken(CsTokenType.This, SymbolType.This, thisExpressionReference)); expression = new LiteralExpression(new CsTokenList(this.tokens, tokenNode, tokenNode), tokenNode); thisExpressionReference.Target = expression; break; case SymbolType.Base: var baseExpressionReference = new Reference<ICodePart>(); tokenNode = this.tokens.InsertLast(this.GetToken(CsTokenType.Base, SymbolType.Base, baseExpressionReference)); expression = new LiteralExpression(new CsTokenList(this.tokens, tokenNode, tokenNode), tokenNode); baseExpressionReference.Target = expression; break; case SymbolType.Multiplication: if (!unsafeCode) { goto default; } expression = this.GetUnsafeAccessExpression(parentReference, unsafeCode); break; case SymbolType.LogicalAnd: if (!unsafeCode) { goto default; } expression = this.GetUnsafeAccessExpression(parentReference, unsafeCode); break; default: throw new SyntaxException(this.document.SourceCode, symbol.LineNumber); } } // Gather up all extensions to this expression. while (expression != null) { var expressionReference = new Reference<ICodePart>(expression); // Check if there is an extension to this expression. Expression extension = this.GetExpressionExtension(expression, previousPrecedence, expressionReference, unsafeCode, typeExpression, allowVariableDeclaration); if (extension != null) { // The larger expression is what we want to return here. expression = extension; } else { // There are no more extensions. break; } } // Return the expression. return expression; }
private static bool CheckPrecedence(ExpressionPrecedence previousPrecedence, ExpressionPrecedence nextPrecedence) { if (((previousPrecedence != ExpressionPrecedence.None) || (nextPrecedence != ExpressionPrecedence.None)) && ((previousPrecedence != ExpressionPrecedence.Conditional) || (nextPrecedence != ExpressionPrecedence.Conditional))) { return (previousPrecedence > nextPrecedence); } return true; }
/// <summary> /// Reads an expression beginning with an opening parenthesis. /// </summary> /// <param name="previousPrecedence">The precedence of the previous expression.</param> /// <param name="unsafeCode">Indicates whether the code being parsed resides in an unsafe code block.</param> /// <returns>Returns the expression.</returns> private Expression GetOpenParenthesisExpression(ExpressionPrecedence previousPrecedence, bool unsafeCode) { Param.Ignore(previousPrecedence, unsafeCode); Expression expression = null; // Now check whether this is a cast. if (this.IsCastExpression(previousPrecedence, unsafeCode)) { expression = this.GetCastExpression(unsafeCode); } else { // This is an expression wrapped in parenthesis. expression = this.GetParenthesizedExpression(unsafeCode); } return expression; }
private RelationalExpression GetRelationalExpression(Expression leftHandSide, ExpressionPrecedence previousPrecedence, bool unsafeCode) { RelationalExpression expression = null; RelationalExpression.Operator equalTo; OperatorSymbol item = this.PeekOperatorToken(); ExpressionPrecedence operatorPrecedence = GetOperatorPrecedence(item.SymbolType); if (!CheckPrecedence(previousPrecedence, operatorPrecedence)) { return expression; } this.symbols.Advance(); this.tokens.Add(item); Expression operatorRightHandExpression = this.GetOperatorRightHandExpression(operatorPrecedence, unsafeCode); CsTokenList tokens = new CsTokenList(this.tokens, leftHandSide.Tokens.First, this.tokens.Last); switch (item.SymbolType) { case OperatorType.ConditionalEquals: equalTo = RelationalExpression.Operator.EqualTo; break; case OperatorType.NotEquals: equalTo = RelationalExpression.Operator.NotEqualTo; break; case OperatorType.LessThan: equalTo = RelationalExpression.Operator.LessThan; break; case OperatorType.GreaterThan: equalTo = RelationalExpression.Operator.GreaterThan; break; case OperatorType.LessThanOrEquals: equalTo = RelationalExpression.Operator.LessThanOrEqualTo; break; case OperatorType.GreaterThanOrEquals: equalTo = RelationalExpression.Operator.GreaterThanOrEqualTo; break; default: throw new InvalidOperationException(); } return new RelationalExpression(tokens, equalTo, leftHandSide, operatorRightHandExpression); }
/// <summary> /// Reads a primary increment expression. /// </summary> /// <param name="leftHandSide">The expression on the left hand side of the operator.</param> /// <param name="previousPrecedence">The precedence of the expression just before this one.</param> /// <returns>Returns the expression.</returns> private IncrementExpression GetPrimaryIncrementExpression( Expression leftHandSide, ExpressionPrecedence previousPrecedence) { Param.AssertNotNull(leftHandSide, "leftHandSide"); Param.Ignore(previousPrecedence); IncrementExpression expression = null; // Check the previous precedence to see if we are allowed to gather up the as expression. if (CheckPrecedence(previousPrecedence, ExpressionPrecedence.Primary)) { var expressionReference = new Reference<ICodePart>(); // Make sure the left hand side has at least one token. Debug.Assert(leftHandSide.Tokens.First != null, "The left hand side should not be empty."); // Get the increment symbol. this.tokens.Add(this.GetOperatorToken(OperatorType.Increment, expressionReference)); // Create the partial token list for the expression. CsTokenList partialTokens = new CsTokenList(this.tokens, leftHandSide.Tokens.First, this.tokens.Last); // Create and return the expression. expression = new IncrementExpression(partialTokens, leftHandSide, IncrementExpression.IncrementType.Postfix); expressionReference.Target = expression; } return expression; }
private UnsafeAccessExpression GetUnsafeTypeExpression(Expression type, ExpressionPrecedence previousPrecedence) { UnsafeAccessExpression expression = null; OperatorType addressOf; UnsafeAccessExpression.Operator dereference; if (!CheckPrecedence(previousPrecedence, ExpressionPrecedence.Unary)) { return expression; } Symbol nextSymbol = this.GetNextSymbol(); if (nextSymbol.SymbolType == SymbolType.LogicalAnd) { addressOf = OperatorType.AddressOf; dereference = UnsafeAccessExpression.Operator.AddressOf; } else { if (nextSymbol.SymbolType != SymbolType.Multiplication) { throw new InvalidOperationException(); } addressOf = OperatorType.Dereference; dereference = UnsafeAccessExpression.Operator.Dereference; } this.symbols.Advance(); OperatorSymbol item = new OperatorSymbol(nextSymbol.Text, OperatorCategory.Reference, addressOf, nextSymbol.Location, this.symbols.Generated); this.tokens.Add(item); return new UnsafeAccessExpression(new CsTokenList(this.tokens, type.Tokens.First, this.tokens.Last), dereference, type); }
/// <summary> /// Reads an expression beginning with two unknown words. /// </summary> /// <param name="type">The type of the variable.</param> /// <param name="previousPrecedence">The precedence of the previous expression.</param> /// <param name="unsafeCode">Indicates whether the code being parsed resides in an unsafe code block.</param> /// <returns>Returns the expression.</returns> private VariableDeclarationExpression GetVariableDeclarationExpression( Expression type, ExpressionPrecedence previousPrecedence, bool unsafeCode) { Param.AssertNotNull(type, "type"); Param.Ignore(previousPrecedence); Param.Ignore(unsafeCode); Debug.Assert( type.ExpressionType == ExpressionType.Literal || type.ExpressionType == ExpressionType.MemberAccess, "The left side of a variable declaration must either be a literal or a member access."); VariableDeclarationExpression expression = null; if (CheckPrecedence(previousPrecedence, ExpressionPrecedence.None)) { var expressionReference = new Reference<ICodePart>(); // Convert the type expression to a literal type token expression. LiteralExpression literalType = null; if (type.ExpressionType == ExpressionType.Literal) { literalType = type as LiteralExpression; if (!(literalType.Token is TypeToken)) { literalType = null; } } if (literalType == null) { literalType = this.ConvertTypeExpression(type); } // Get each declarator. List<VariableDeclaratorExpression> declarators = new List<VariableDeclaratorExpression>(); while (true) { // Get the next word. Symbol symbol = this.GetNextSymbol(SymbolType.Other, expressionReference); // Get the identifier. LiteralExpression identifier = this.GetLiteralExpression(expressionReference, unsafeCode); if (identifier == null || identifier.Tokens.First == null) { throw new SyntaxException(this.document.SourceCode, symbol.LineNumber); } // Get the initializer if it exists. Expression initializer = null; symbol = this.GetNextSymbol(expressionReference); if (symbol.SymbolType == SymbolType.Equals) { // Add the equals token. this.tokens.Add(this.GetOperatorToken(OperatorType.Equals, expressionReference)); // Check whether this is an array initializer. symbol = this.GetNextSymbol(expressionReference); if (symbol.SymbolType == SymbolType.OpenCurlyBracket) { initializer = this.GetArrayInitializerExpression(unsafeCode); } else { initializer = this.GetNextExpression(ExpressionPrecedence.None, expressionReference, unsafeCode); } } // Create the token list for the declarator. CsTokenList partialTokens = new CsTokenList( this.tokens, identifier.Tokens.First, this.tokens.Last); // Create and add the declarator. declarators.Add(new VariableDeclaratorExpression(partialTokens, identifier, initializer)); // Now check if the next character is a comma. If so there is another declarator. symbol = this.GetNextSymbol(expressionReference); if (symbol.SymbolType != SymbolType.Comma) { // There are no more declarators. break; } // Add the comma. this.tokens.Add(this.GetToken(CsTokenType.Comma, SymbolType.Comma, expressionReference)); } // Create the token list for the expression. CsTokenList tokenList = new CsTokenList(this.tokens, type.Tokens.First, this.tokens.Last); // Create the expression. expression = new VariableDeclarationExpression(tokenList, literalType, declarators.ToArray()); expressionReference.Target = expression; } return expression; }
private VariableDeclarationExpression GetVariableDeclarationExpression(Expression type, ExpressionPrecedence previousPrecedence, bool unsafeCode) { VariableDeclarationExpression expression = null; Symbol symbol; if (!CheckPrecedence(previousPrecedence, ExpressionPrecedence.None)) { return expression; } LiteralExpression expression2 = null; if (type.ExpressionType == ExpressionType.Literal) { expression2 = type as LiteralExpression; if (!(expression2.Token is TypeToken)) { expression2 = null; } } if (expression2 == null) { expression2 = this.ConvertTypeExpression(type); } List<VariableDeclaratorExpression> list = new List<VariableDeclaratorExpression>(); Label_0042: symbol = this.GetNextSymbol(SymbolType.Other); LiteralExpression literalExpression = this.GetLiteralExpression(unsafeCode); if ((literalExpression == null) || (literalExpression.Tokens.First == null)) { throw new SyntaxException(this.document.SourceCode, symbol.LineNumber); } Expression initializer = null; if (this.GetNextSymbol().SymbolType == SymbolType.Equals) { this.tokens.Add(this.GetOperatorToken(OperatorType.Equals)); if (this.GetNextSymbol().SymbolType == SymbolType.OpenCurlyBracket) { initializer = this.GetArrayInitializerExpression(unsafeCode); } else { initializer = this.GetNextExpression(ExpressionPrecedence.None, unsafeCode); } } CsTokenList tokens = new CsTokenList(this.tokens, literalExpression.Tokens.First, this.tokens.Last); list.Add(new VariableDeclaratorExpression(tokens, literalExpression, initializer)); if (this.GetNextSymbol().SymbolType == SymbolType.Comma) { this.tokens.Add(this.GetToken(CsTokenType.Comma, SymbolType.Comma)); goto Label_0042; } return new VariableDeclarationExpression(new CsTokenList(this.tokens, type.Tokens.First, this.tokens.Last), expression2, list.ToArray()); }
/// <summary> /// Reads an array access expression. /// </summary> /// <param name="array">The array being accessed.</param> /// <param name="previousPrecedence">The precedence of the previous expression.</param> /// <param name="unsafeCode">Indicates whether the code being parsed resides in an unsafe code block.</param> /// <returns>Returns the expression.</returns> private ArrayAccessExpression GetArrayAccessExpression( Expression array, ExpressionPrecedence previousPrecedence, bool unsafeCode) { Param.AssertNotNull(array, "array"); Param.Ignore(previousPrecedence); Param.Ignore(unsafeCode); ArrayAccessExpression expression = null; if (CheckPrecedence(previousPrecedence, ExpressionPrecedence.Primary)) { var expressionReference = new Reference<ICodePart>(); // The next symbol will be the opening bracket. Bracket openingBracket = this.GetBracketToken(CsTokenType.OpenSquareBracket, SymbolType.OpenSquareBracket, expressionReference); Node<CsToken> openingBracketNode = this.tokens.InsertLast(openingBracket); // Get the argument list now. ICollection<Argument> argumentList = this.GetArgumentList(SymbolType.CloseSquareBracket, expressionReference, unsafeCode); // Get the closing bracket. Bracket closingBracket = this.GetBracketToken(CsTokenType.CloseSquareBracket, SymbolType.CloseSquareBracket, expressionReference); Node<CsToken> closingBracketNode = this.tokens.InsertLast(closingBracket); openingBracket.MatchingBracketNode = closingBracketNode; closingBracket.MatchingBracketNode = openingBracketNode; // Pull out the first token from the array. Node<CsToken> firstTokenNode = array.Tokens.First; // Create the token list for the method invocation expression. CsTokenList partialTokens = new CsTokenList(this.tokens, firstTokenNode, this.tokens.Last); // Create and return the expression. expression = new ArrayAccessExpression(partialTokens, array, argumentList); expressionReference.Target = expression; } return expression; }
/// <summary> /// Reads the next expression from the file and returns it. /// </summary> /// <param name="previousPrecedence">The precedence of the expression just before this one.</param> /// <param name="unsafeCode">Indicates whether the code being parsed resides in an unsafe code block.</param> /// <returns>Returns the expression.</returns> private Expression GetNextExpression(ExpressionPrecedence previousPrecedence, bool unsafeCode) { Param.Ignore(previousPrecedence); Param.Ignore(unsafeCode); return this.GetNextExpression(previousPrecedence, unsafeCode, false, false); }
/// <summary> /// Reads an assignment expression. /// </summary> /// <param name="leftHandSide">The expression on the left hand side of the operator.</param> /// <param name="previousPrecedence">The precedence of the expression just before this one.</param> /// <param name="parentReference">The parent code part.</param> /// <param name="unsafeCode">Indicates whether the code being parsed resides in an unsafe code block.</param> /// <returns>Returns the expression.</returns> private AssignmentExpression GetAssignmentExpression( Expression leftHandSide, ExpressionPrecedence previousPrecedence, Reference<ICodePart> parentReference, bool unsafeCode) { Param.AssertNotNull(leftHandSide, "leftHandSide"); Param.Ignore(previousPrecedence); Param.Ignore(parentReference, "parentReference"); Param.Ignore(unsafeCode); AssignmentExpression expression = null; var expressionReference = new Reference<ICodePart>(); // Read the details of the expression. OperatorSymbol operatorToken = this.PeekOperatorToken(parentReference, expressionReference); Debug.Assert(operatorToken.Category == OperatorCategory.Assignment, "Expected an assignment operator"); // Check the precedence of the operators to make sure we can gather this statement now. ExpressionPrecedence precedence = GetOperatorPrecedence(operatorToken.SymbolType); if (CheckPrecedence(previousPrecedence, precedence)) { // Add the operator token to the document and advance the symbol manager up to it. this.symbols.Advance(); this.tokens.Add(operatorToken); // Get the expression on the right-hand side of the operator. Expression rightHandSide = this.GetOperatorRightHandExpression(ExpressionPrecedence.None, expressionReference, unsafeCode); // Create the partial token list for the expression. CsTokenList partialTokens = new CsTokenList(this.tokens, leftHandSide.Tokens.First, this.tokens.Last); // Get the expression operator type. AssignmentExpression.Operator type; switch (operatorToken.SymbolType) { case OperatorType.Equals: type = AssignmentExpression.Operator.Equals; break; case OperatorType.PlusEquals: type = AssignmentExpression.Operator.PlusEquals; break; case OperatorType.MinusEquals: type = AssignmentExpression.Operator.MinusEquals; break; case OperatorType.MultiplicationEquals: type = AssignmentExpression.Operator.MultiplicationEquals; break; case OperatorType.DivisionEquals: type = AssignmentExpression.Operator.DivisionEquals; break; case OperatorType.AndEquals: type = AssignmentExpression.Operator.AndEquals; break; case OperatorType.OrEquals: type = AssignmentExpression.Operator.OrEquals; break; case OperatorType.XorEquals: type = AssignmentExpression.Operator.XorEquals; break; case OperatorType.ModEquals: type = AssignmentExpression.Operator.ModEquals; break; case OperatorType.LeftShiftEquals: type = AssignmentExpression.Operator.LeftShiftEquals; break; case OperatorType.RightShiftEquals: type = AssignmentExpression.Operator.RightShiftEquals; break; default: Debug.Fail("Unexpected operator type"); throw new InvalidOperationException(); } // Create and return the expression. expression = new AssignmentExpression(partialTokens, type, leftHandSide, rightHandSide); expressionReference.Target = expression; } return expression; }
/// <summary> /// Reads the next expression from a conditional preprocessor directive. /// </summary> /// <param name="document">The parent document.</param> /// <param name="parentProxy">Represents the parent item.</param> /// <param name="previousPrecedence">The precedence of the expression just before this one.</param> /// <returns>Returns the expression.</returns> private Expression GetNextConditionalPreprocessorExpression(CsDocument document, CodeUnitProxy parentProxy, ExpressionPrecedence previousPrecedence) { Param.AssertNotNull(document, "document"); Param.AssertNotNull(parentProxy, "parentProxy"); Param.Ignore(previousPrecedence); // Move past comments and whitepace. this.AdvanceToNextConditionalDirectiveCodeSymbol(parentProxy); // Saves the next expression. Expression expression = null; CodeUnitProxy expressionExtensionProxy = new CodeUnitProxy(this.document); // Get the next symbol. Symbol symbol = this.symbols.Peek(1); if (symbol != null) { switch (symbol.SymbolType) { case SymbolType.Other: expression = this.GetConditionalPreprocessorConstantExpression(expressionExtensionProxy); break; case SymbolType.Not: expression = this.GetConditionalPreprocessorNotExpression(expressionExtensionProxy); break; case SymbolType.OpenParenthesis: expression = this.GetConditionalPreprocessorParenthesizedExpression(expressionExtensionProxy); break; case SymbolType.False: expression = this.CreateLiteralExpression(expressionExtensionProxy, symbol.SymbolType, TokenType.False); break; case SymbolType.True: expression = this.CreateLiteralExpression(expressionExtensionProxy, symbol.SymbolType, TokenType.True); break; default: throw new SyntaxException(this.document, symbol.LineNumber); } } // Gather up all extensions to this expression. Expression topLevelExpression = expression; // Gather up all extensions to this expression. while (expression != null) { // Check if there is an extension to this expression. Expression extension = this.GetConditionalPreprocessorExpressionExtension(expressionExtensionProxy, expression, previousPrecedence); if (extension != null) { // Save the expression extension proxy and create a new one for the next expression extension. expressionExtensionProxy = new CodeUnitProxy(this.document); expressionExtensionProxy.Children.Add(expression); topLevelExpression = expression; } else { // There are no more extensions. break; } } // There are no more extensions. The children of the current top-level expression extension proxy // should actually be children of the parent proxy, since there are no more extensions. CodeUnit unit = expressionExtensionProxy.Children.First; while (unit != null) { CodeUnit next = unit.LinkNode.Next; unit.Detach(); unit.LinkNode.ContainingList = null; parentProxy.Children.Add(unit); unit = next; } // Return the expression. return(topLevelExpression); }