public virtual object VisitElementAccessExpression(ElementAccessExpression elementAccessExpression, object data) { stackMap.Push(elementAccessExpression); elementAccessExpression.LeftSide.AcceptVisitor(this, data); elementAccessExpression.Expressions.AcceptVisitor(this, data); stackMap.Pop(); return(null); }
private ExpressionNode ParseSubexpression(int precBound, ExpressionNode left) { while (true) { int curPrec = precedence[(int)curtok.ID]; if (curPrec < precBound) break; int associativity = ASSOC_LEFT; TokenID curOp = curtok.ID; switch (curOp) { case TokenID.Equal: case TokenID.PlusEqual: case TokenID.MinusEqual: case TokenID.StarEqual: case TokenID.SlashEqual: case TokenID.PercentEqual: case TokenID.BAndEqual: case TokenID.BOrEqual: case TokenID.BXorEqual: case TokenID.ShiftLeftEqual: case TokenID.QuestionQuestion: associativity = ASSOC_RIGHT; goto case TokenID.Percent; // "FALL THROUGH" case TokenID.Greater: Advance(); if (curtok.ID == TokenID.Greater && curtok.LastCharWasGreater) { curOp = TokenID.ShiftRight; Advance(); } else if (curtok.ID == TokenID.GreaterEqual && curtok.LastCharWasGreater) { curOp = TokenID.ShiftRightEqual; associativity = ASSOC_RIGHT; Advance(); } goto parseBinOp; case TokenID.Or: case TokenID.And: case TokenID.BOr: case TokenID.BXor: case TokenID.BAnd: case TokenID.EqualEqual: case TokenID.NotEqual: case TokenID.Less: case TokenID.LessEqual: case TokenID.GreaterEqual: case TokenID.ShiftLeft: case TokenID.Plus: case TokenID.Minus: case TokenID.Star: case TokenID.Slash: case TokenID.Percent: Advance(); parseBinOp: left = new BinaryExpression(curOp, left, ParseSubexpression(curPrec + associativity)); break; case TokenID.PlusPlus: // postfix Advance(); left = new PostIncrementExpression(left); break; case TokenID.MinusMinus: // postfix Advance(); left = new PostDecrementExpression(left); break; case TokenID.Is: case TokenID.As: Advance(); left = new BinaryExpression(curOp, left, ParseType(true)); break; case TokenID.Question: { Advance(); ExpressionNode thenExpr = ParseExpression(); AssertAndAdvance(TokenID.Colon); left = new ConditionalExpression(left, thenExpr, ParseExpression()); break; } case TokenID.LParen: // invocation Advance(); left = new InvocationExpression(left, ParseArgumentList()); AssertAndAdvance(TokenID.RParen); break; case TokenID.LBracket: // element access Advance(); left = new ElementAccessExpression(left, ParseExpressionList()); AssertAndAdvance(TokenID.RBracket); break; case TokenID.Dot: // member access case TokenID.MinusGreater: left = ParseMemberAccess(left); break; default: ReportError("Unexpected token", curtok); return left; } } return left; }
private ExpressionNode ParseExpressionOrType(bool inStatementContext) { // Can the interior be a type? (A.2.2) switch (curtok.ID) { // type-name case TokenID.Ident: // simple-type case TokenID.SByte: case TokenID.Byte: case TokenID.Short: case TokenID.UShort: case TokenID.Int: case TokenID.UInt: case TokenID.Long: case TokenID.ULong: case TokenID.Char: case TokenID.Float: case TokenID.Double: case TokenID.Decimal: case TokenID.Bool: // class-type case TokenID.Object: case TokenID.String: // yes, it can break; default: // no, it can not return ParseExpression(); } ExpressionNode expr = ParseIdentifierOrKeyword(false, false, false, false, false); if (curtok.ID == TokenID.ColonColon) { // id :: id type-parameter-list_opt QualifiedIdentifierExpression qualID = new QualifiedIdentifierExpression(curtok); // TODO: Replace by QualifiedAliasMember instance qualID.IsNamespaceAliasQualifier = true; qualID.Expressions.Add(expr); Advance(); // over ColonColon qualID.Expressions.Add(ParseMember(inStatementContext)); expr = qualID; } else if (ParsePossibleTypeParameterNode(false, false, false, inStatementContext)) { expr = new TypeNode(expr); ApplyTypeParameters((TypeNode)expr); } while (curtok.ID == TokenID.Dot) { Advance(); // over Dot if (curtok.ID != TokenID.Ident) { RecoverFromError(TokenID.Ident); return expr; } expr = new MemberAccessExpression(expr, ParseMember(inStatementContext), TokenID.Dot); } bool hasQuestionMark = false; int starCount = 0; bool hasBracket = false; if (curtok.ID == TokenID.Question) { Advance(); hasQuestionMark = true; } while (curtok.ID == TokenID.Star) { Advance(); starCount++; } // return (a * b); // return (a ? b : c); // a* b = c; // a? b = c; // a b = c; //if(curtok.ID == TokenID.Ident || (hasQuestionMark || starCount > 0) && curtok.ID == TokenID.RParen) goto foundType; if (curtok.ID == TokenID.Ident) { if (inStatementContext) goto foundType; else if (!hasQuestionMark && starCount == 0) goto foundType; // it is a parse error } else if (curtok.ID == TokenID.RParen) { if (hasQuestionMark || starCount > 0) goto foundType; } else if (curtok.ID == TokenID.LBracket) { Advance(); hasBracket = true; if (hasQuestionMark || starCount > 0 || curtok.ID == TokenID.Comma || curtok.ID == TokenID.RBracket) goto foundType; } // // treat as expression // if (hasQuestionMark) { // hasBracket is false ExpressionNode trueExpr = ParseSubexpression(starCount > 0 ? (int)PRECEDENCE_UNARY : 1); while (starCount-- > 0) trueExpr = new DereferenceExpression(trueExpr); AssertAndAdvance(TokenID.Colon); return new ConditionalExpression(expr, trueExpr, ParseExpression()); } else if (starCount > 0) { // hasBracket is false starCount--; ExpressionNode right = ParseSubexpression(starCount > 0 ? PRECEDENCE_UNARY : PRECEDENCE_MULTIPLICATIVE + ASSOC_LEFT); while (starCount-- > 0) right = new DereferenceExpression(right); expr = new BinaryExpression(TokenID.Star, expr, right); } else if (hasBracket) { expr = new ElementAccessExpression(expr, ParseExpressionList()); AssertAndAdvance(TokenID.RBracket); } return ParseSubexpression(1, expr); // // treat as type // foundType: TypeNode typeNode = new TypeNode(expr); if (hasQuestionMark) typeNode.IsNullableType = true; while (starCount-- > 0) typeNode = new TypePointerNode(typeNode); if (hasBracket) { while (true) { int numCommas = 0; while (curtok.ID == TokenID.Comma) { Advance(); numCommas++; } AssertAndAdvance(TokenID.RBracket); typeNode.RankSpecifiers.Add(numCommas); if (curtok.ID != TokenID.LBracket) break; Advance(); } } return typeNode; }
private ExpressionNode ParsePrimaryExpression() { Token tok = curtok; ExpressionNode result; // TODO: handle error cases (result = null) switch (curtok.ID) { #region Literals case TokenID.Null: result = new NullPrimitive(curtok); Advance(); break; case TokenID.True: result = new BooleanPrimitive(true, curtok); Advance(); break; case TokenID.False: result = new BooleanPrimitive(false, curtok); Advance(); break; case TokenID.IntLiteral: result = new IntegralPrimitive(strings[curtok.Data], IntegralType.Int, curtok); Advance(); break; case TokenID.UIntLiteral: result = new IntegralPrimitive(strings[curtok.Data], IntegralType.UInt, curtok); Advance(); break; case TokenID.LongLiteral: result = new IntegralPrimitive(strings[curtok.Data], IntegralType.Long, curtok); Advance(); break; case TokenID.ULongLiteral: result = new IntegralPrimitive(strings[curtok.Data], IntegralType.ULong, curtok); Advance(); break; case TokenID.RealLiteral: result = new RealPrimitive(strings[curtok.Data], curtok); Advance(); break; case TokenID.CharLiteral: result = new CharPrimitive(strings[curtok.Data], curtok); Advance(); break; case TokenID.StringLiteral: result = new StringPrimitive(strings[curtok.Data], curtok); Advance(); break; #endregion #region Predefined Types case TokenID.Bool: case TokenID.Byte: case TokenID.Char: case TokenID.Decimal: case TokenID.Double: case TokenID.Float: case TokenID.Int: case TokenID.Long: case TokenID.Object: case TokenID.SByte: case TokenID.Short: case TokenID.String: case TokenID.UInt: case TokenID.ULong: case TokenID.UShort: result = new PredefinedTypeNode(tok.ID, tok); Advance(); result = ParseMemberAccess(result); break; #endregion #region Keywords case TokenID.This: { Advance(); IdentifierExpression idExpr = new IdentifierExpression("this", tok); idExpr.StartingPredefinedType = tok.ID; result = idExpr; break; } case TokenID.Base: Advance(); // over base if (curtok.ID == TokenID.LBracket) // base indexer expression { Advance(); result = new ElementAccessExpression(new IdentifierExpression("base", tok), ParseExpressionList()); AssertAndAdvance(TokenID.RBracket); break; } if (curtok.ID != TokenID.Dot) { RecoverFromError(TokenID.Dot, TokenID.LBracket); result = null; break; } // base access expression Advance(); // advance over dot result = new BaseAccessExpression(ParseMember(false)); break; case TokenID.Checked: Advance(); AssertAndAdvance(TokenID.LParen); result = new CheckedExpression(ParseExpression()); AssertAndAdvance(TokenID.RParen); break; case TokenID.Unchecked: Advance(); AssertAndAdvance(TokenID.LParen); result = new UncheckedExpression(ParseExpression()); AssertAndAdvance(TokenID.RParen); break; case TokenID.Default: Advance(); AssertAndAdvance(TokenID.LParen); result = new DefaultConstantExpression(ParseType(false)); AssertAndAdvance(TokenID.RParen); break; case TokenID.New: Advance(); isNewStatement = true; IType newType = ParseType(false); //ApplyTypeParameters(newType); -> not sure, but a type pointer can not be generic! if (curtok.ID == TokenID.LParen) { Advance(); result = new ObjectCreationExpression(newType, ParseArgumentList(), tok); AssertAndAdvance(TokenID.RParen); } else if (curtok.ID == TokenID.LBracket) { result = ParseArrayCreation(newType); } else { RecoverFromError(TokenID.LParen, TokenID.LBracket); result = null; } isNewStatement = false; break; case TokenID.Typeof: Advance(); AssertAndAdvance(TokenID.LParen); result = new TypeOfExpression(ParseType(false)); CheckRankSpecifier(result); AssertAndAdvance(TokenID.RParen); break; case TokenID.Sizeof: Advance(); AssertAndAdvance(TokenID.LParen); result = new SizeOfExpression(ParseType(false)); AssertAndAdvance(TokenID.RParen); break; case TokenID.Delegate: //anonymous method Advance(); result = ParseAnonymousMethod(); break; #endregion Keywords case TokenID.Ident: result = ParseIdentifierOrKeyword(false, false, false, false, false); if (curtok.ID == TokenID.ColonColon) { // id :: id type-parameter-list_opt . id type-parameter-list_opt QualifiedIdentifierExpression qualID = new QualifiedIdentifierExpression(curtok); // TODO: Replace by QualifiedAliasMember instance qualID.IsNamespaceAliasQualifier = true; qualID.Expressions.Add(result); Advance(); // over ColonColon qualID.Expressions.Add(ParseMember(false)); result = ParseMemberAccess(qualID); } else if (ParsePossibleTypeParameterNode(false, false, false, false)) { result = new TypeNode(result); ApplyTypeParameters((TypeNode)result); } break; case TokenID.LParen: Advance(); result = ParseCastOrGroup(); break; default: RecoverFromError("Unexpected token in primary expression"); return null; // TODO: Invalid expression } return result; }
public virtual object VisitElementAccessExpression(ElementAccessExpression elementAccessExpression, object data) { stackMap.Push(elementAccessExpression); elementAccessExpression.LeftSide.AcceptVisitor(this, data); elementAccessExpression.Expressions.AcceptVisitor(this, data); stackMap.Pop(); return null; }