Пример #1
0
 private Expression ParseNew(TokenSet followers){
   SourceContext ctx = this.scanner.CurrentSourceContext;
   Debug.Assert(this.currentToken == Token.New);
   this.GetNextToken();
   TypeNode allocator = null;
   if (this.currentToken == Token.LeftBracket) {
     this.GetNextToken();
     if (this.currentToken == Token.RightBracket) {
       return this.ParseNewImplicitlyTypedArray(ctx, followers);
     }
     // parse [Delayed] annotation (or allocator)
     allocator = this.ParseBaseTypeExpression(null, followers|Token.RightBracket, false, false);
     if (allocator == null){this.SkipTo(followers, Error.None); return null;}
     this.Skip(Token.RightBracket);
   }
   if (this.currentToken == Token.LeftBrace)
     return this.ParseNewAnonymousTypeInstance(ctx, followers);
   Expression owner = null;
   // Allow owner argument for each constructor: "new <ow> ..."
   if (this.currentToken == Token.LessThan) {
     this.GetNextToken();
     owner = this.ParsePrimaryExpression(followers | Token.GreaterThan);
     if (this.currentToken == Token.GreaterThan)
       this.GetNextToken();
   }
   // Make it explicit that the base type stops at "!", which is handled by
   // the code below.
   TypeNode t = this.ParseBaseTypeExpression(null, followers|Parser.InfixOperators|Token.LeftBracket|Token.LeftParenthesis|Token.RightParenthesis|Token.LogicalNot, false, false);
   if (t == null){this.SkipTo(followers, Error.None); return null;}
   if (this.currentToken == Token.Conditional) {
     TypeNode type = t;
     t = new NullableTypeExpression(type);
     t.SourceContext = type.SourceContext;
     t.SourceContext.EndPos = this.scanner.endPos;
     this.GetNextToken();
   }else if (this.currentToken == Token.LogicalNot){
     TypeNode type = t;
     t = new NonNullableTypeExpression(type);
     t.SourceContext = type.SourceContext;
     t.SourceContext.EndPos = this.scanner.endPos;
     this.GetNextToken();
   }else if (this.currentToken == Token.Multiply){
     this.GetNextToken();
     t = new PointerTypeExpression(t, t.SourceContext);
     t.SourceContext.EndPos = this.scanner.endPos;
     if (!this.inUnsafeCode)
       this.HandleError(t.SourceContext, Error.UnsafeNeeded);
   }
   ctx.EndPos = t.SourceContext.EndPos;
   // special hack [Delayed] in custom allocator position is used to mark the array as
   // a delayed construction. This annotation is used in the Definite Assignment analysis.
   //
   TypeExpression allocatorExp = allocator as TypeExpression;
   if (allocatorExp != null) {
     Identifier allocId = allocatorExp.Expression as Identifier;
     if (allocId != null && allocId.Name == "Delayed") {
       t = new RequiredModifierTypeExpression(t, TypeExpressionFor("Microsoft","Contracts","DelayedAttribute"));
       allocator = null; // not really a custom allocation
     }
   }
   int rank = this.ParseRankSpecifier(false, followers|Token.LeftBrace|Token.LeftBracket|Token.LeftParenthesis|Token.RightParenthesis);
   SourceContext lbCtx = ctx;
   while (rank > 0 && this.currentToken == Token.LeftBracket){
     lbCtx = this.scanner.CurrentSourceContext;
     t = new ArrayTypeExpression(t, rank);
     rank = this.ParseRankSpecifier(false, followers|Token.LeftBrace|Token.LeftBracket);
   }
   if (rank > 0){
     //new T[] {...} or new T[,] {{..} {...}...}, etc where T can also be an array type
     ConstructArray consArr = new ConstructArray();
     consArr.SourceContext = ctx;
     consArr.ElementType = consArr.ElementTypeExpression = t;
     consArr.Rank = rank;
     if (this.currentToken == Token.LeftBrace)
       consArr.Initializers = this.ParseArrayInitializer(rank, t, followers);
     else{
       if (Parser.UnaryStart[this.currentToken])
         this.HandleError(Error.ExpectedLeftBrace);
       else
         this.HandleError(Error.MissingArraySize);
       while (Parser.UnaryStart[this.currentToken]){
         this.ParseExpression(followers|Token.Comma|Token.RightBrace);
         if (this.currentToken != Token.Comma) break;
         this.GetNextToken();
       }
       if (this.currentToken == Token.RightBrace) this.GetNextToken();
       this.SkipTo(followers);
     }
     if (owner != null) {
       consArr.Owner = owner;
     }
     return consArr;
   }
   if (rank < 0){
     //new T[x] or new T[x,y] etc. possibly followed by an initializer or element type rank specifier
     ConstructArray consArr = new ConstructArray();
     consArr.SourceContext = ctx;
     consArr.Operands = this.ParseIndexList(followers|Token.LeftBrace|Token.LeftBracket, lbCtx, out consArr.SourceContext.EndPos);
     rank = consArr.Operands.Count;
     if (this.currentToken == Token.LeftBrace)
       consArr.Initializers = this.ParseArrayInitializer(rank, t, followers);
     else{
       int elementRank = this.ParseRankSpecifier(true, followers);
     tryAgain:
       if (elementRank > 0) t = this.ParseArrayType(elementRank, t, followers);
       if (this.currentToken == Token.LeftBrace)
         consArr.Initializers = this.ParseArrayInitializer(rank, t, followers);
       else{
         if (this.currentToken == Token.LeftBracket){ //new T[x][y] or something like that
           lbCtx = this.scanner.CurrentSourceContext;
           this.GetNextToken();
           SourceContext sctx = this.scanner.CurrentSourceContext;
           this.ParseIndexList(followers, lbCtx, out sctx.EndPos);
           this.HandleError(sctx, Error.InvalidArray);
           elementRank = 1;
           goto tryAgain;
         }else
           this.SkipTo(followers);
       }
     }
     consArr.ElementType = consArr.ElementTypeExpression = t;
     consArr.Rank = rank;
     if (owner != null) {
       consArr.Owner = owner;
     }
     return consArr;
   }
   ExpressionList arguments = null;
   SourceContext lpCtx = this.scanner.CurrentSourceContext;
   bool sawLeftParenthesis = false;
   if (this.currentToken == Token.LeftParenthesis){
     if (rank == 0 && t is NonNullableTypeExpression) {
       this.SkipTo(followers, Error.BadNewExpr);
       return null;
     }
     sawLeftParenthesis = true;
     this.GetNextToken();
     arguments = this.ParseArgumentList(followers, lpCtx, out ctx.EndPos);
   }else if (this.currentToken == Token.LeftBrace){
     Expression quant = this.ParseComprehension(followers);
     arguments = new ExpressionList(quant);
   }else{
     this.SkipTo(followers, Error.BadNewExpr);
     Construct c = new Construct();
     if (t is TypeExpression)
       c.Constructor = new MemberBinding(null, t, t.SourceContext);
     c.SourceContext = ctx;
     return c;
   }
   if (sawLeftParenthesis && this.currentToken == Token.LeftBrace){
   }
   Construct cons = new Construct(new MemberBinding(null, t), arguments);
   cons.SourceContext = ctx;
   if (owner != null)
     cons.Owner = owner;
   return cons;
 }
Пример #2
0
 private TypeNode ParseTypeExpression(Identifier id, TokenSet followers, bool returnNullIfError, bool AsOrIs, bool Typeof){
   TokenSet followersOrTypeOperator = followers|Parser.TypeOperator;
   TypeNode type = this.ParseBaseTypeExpression(id, followersOrTypeOperator, returnNullIfError, Typeof);
   if (type == null){
     if (!returnNullIfError) this.SkipTo(followers, Error.None);
     return null;
   }
   TypeNode baseType = type;
   int rank = this.ParseRankSpecifier(returnNullIfError, followersOrTypeOperator);
   if (rank > 0){
     returnNullIfError = false; //No longer ambiguous
     type = this.ParseArrayType(rank, type, followersOrTypeOperator);
   }else if (this.currentToken == Token.LeftBracket && returnNullIfError)
     return null;
   else if (rank == -1){
     this.currentToken = Token.LeftBracket;
     this.scanner.endPos = type.SourceContext.EndPos;
     this.GetNextToken();
     goto done;
   }
   for(;;){
     switch(this.currentToken){
       case Token.BitwiseAnd:
         if (returnNullIfError) goto done;
         this.HandleError(Error.ExpectedIdentifier); //TODO: this matches C#, but a better error would be nice
         this.GetNextToken();
         break;
       case Token.LeftBracket:
         returnNullIfError = false;
         rank = this.ParseRankSpecifier(false, followersOrTypeOperator);
         if (rank > 0) type = this.ParseArrayType(rank, type, followersOrTypeOperator);
         break;
       case Token.Multiply:{
         TypeNode t = new PointerTypeExpression(type);
         t.DeclaringModule = this.module;
         t.SourceContext = type.SourceContext;
         t.SourceContext.EndPos = this.scanner.endPos;
         type = t;
         this.GetNextToken();
         if (!this.inUnsafeCode){
           if (!returnNullIfError)
             this.HandleError(t.SourceContext, Error.UnsafeNeeded);
         }
         break;}
       case Token.LogicalNot:{
         TypeNode t = new NonNullableTypeExpression(type);
         t.SourceContext = type.SourceContext;
         t.SourceContext.EndPos = this.scanner.endPos;
         type = t;
         this.GetNextToken();
         break;}
       case Token.Conditional:{
         if (AsOrIs && Parser.NullableTypeNonFollower[PeekToken()]) goto done;
         TypeNode t = new NullableTypeExpression(type);
         t.SourceContext = type.SourceContext;
         t.SourceContext.EndPos = this.scanner.endPos;
         type = t;
         this.GetNextToken();
         break;}
       default:
         goto done;
     }
   }
 done:
   if (returnNullIfError && !followers[this.currentToken]) return null;
   this.SkipTo(followers);
   return type;
 }