/// <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> /// Gets an object initializer expression. /// </summary> /// <param name="unsafeCode">Indicates whether the code being parsed resides in an unsafe code block.</param> /// <returns>Returns the expression.</returns> private ObjectInitializerExpression GetObjectInitializerExpression(bool unsafeCode) { Param.Ignore(unsafeCode); var expressionReference = new Reference<ICodePart>(); List<AssignmentExpression> initializerExpressions = new List<AssignmentExpression>(); // Add and move past the opening curly bracket. Bracket openingBracket = this.GetBracketToken(CsTokenType.OpenCurlyBracket, SymbolType.OpenCurlyBracket, expressionReference); Node<CsToken> openingBracketNode = this.tokens.InsertLast(openingBracket); while (true) { // If the next symbol is the closing curly bracket, then we are done. Symbol symbol = this.GetNextSymbol(expressionReference); if (symbol.SymbolType == SymbolType.CloseCurlyBracket) { break; } var initializerExpressionReference = new Reference<ICodePart>(); // Get the identifier. LiteralExpression identifier = this.GetLiteralExpression(initializerExpressionReference, unsafeCode); // Get the equals sign. symbol = this.GetNextSymbol(initializerExpressionReference); if (symbol.SymbolType != SymbolType.Equals) { throw this.CreateSyntaxException(); } this.tokens.Add(this.GetOperatorToken(OperatorType.Equals, initializerExpressionReference)); // Get the initializer value. If this begins with an opening curly bracket, // this is an embedded object or collection initializer. Otherwise, it is // some other kind of expression. Expression initializerValue = null; symbol = this.GetNextSymbol(initializerExpressionReference); if (symbol.SymbolType == SymbolType.OpenCurlyBracket) { initializerValue = this.GetObjectOrCollectionInitializerExpression(initializerExpressionReference, unsafeCode); } else { initializerValue = this.GetNextExpression(ExpressionPrecedence.None, initializerExpressionReference, unsafeCode); } // Create and add this initializer. CsTokenList initializerTokens = new CsTokenList(this.tokens, identifier.Tokens.First, initializerValue.Tokens.Last); var initializerExpression = new AssignmentExpression( initializerTokens, AssignmentExpression.Operator.Equals, identifier, initializerValue); initializerExpressionReference.Target = initializerExpression; initializerExpressions.Add(initializerExpression); // Check whether we're done. symbol = this.GetNextSymbol(expressionReference); if (symbol.SymbolType == SymbolType.Comma) { this.tokens.Add(this.GetToken(CsTokenType.Comma, SymbolType.Comma, expressionReference)); // If the next symbol after this is the closing curly bracket, then we are done. symbol = this.GetNextSymbol(expressionReference); if (symbol.SymbolType == SymbolType.CloseCurlyBracket) { break; } } else { break; } } // Add and move past the closing curly bracket. Bracket closingBracket = this.GetBracketToken(CsTokenType.CloseCurlyBracket, SymbolType.CloseCurlyBracket, expressionReference); Node<CsToken> closingBracketNode = this.tokens.InsertLast(closingBracket); openingBracket.MatchingBracketNode = closingBracketNode; closingBracket.MatchingBracketNode = openingBracketNode; // Create the token list for the overall expression. CsTokenList expressionTokens = new CsTokenList(this.tokens, openingBracketNode, closingBracketNode); // Create and return the expression. var expression = new ObjectInitializerExpression(expressionTokens, initializerExpressions.ToArray()); expressionReference.Target = expression; return expression; }