示例#1
0
    private Expression ParsePrimaryExpression(TokenSet followers){
      Expression expression = null;
      SourceContext sctx = this.scanner.CurrentSourceContext;
      switch(this.currentToken){
        case Token.ArgList:
          this.GetNextToken();
          expression = new ArglistExpression(sctx);
          break;
        case Token.Delegate:{
          this.GetNextToken();
          ParameterList parameters = null;
          if (this.currentToken == Token.LeftParenthesis)
            parameters = this.ParseParameters(Token.RightParenthesis, followers|Token.LeftBrace);
          Block block = null;
          if (this.currentToken == Token.LeftBrace)
            block = this.ParseBlock(this.scanner.CurrentSourceContext, followers);
          else
            this.SkipTo(followers, Error.ExpectedLeftBrace);
          sctx.EndPos = this.scanner.endPos;
          return new AnonymousNestedDelegate(parameters, block, sctx);}
        case Token.New:
          expression = this.ParseNew(followers|Token.Dot|Token.LeftBracket|Token.Arrow);
          break;
        case Token.Identifier:
          expression = this.scanner.GetIdentifier();
          if (this.sink != null) {
            this.sink.StartName((Identifier)expression);
          }
          this.GetNextToken();
          if (this.currentToken == Token.DoubleColon){
            this.GetNextToken();
            Identifier id = this.scanner.GetIdentifier();
            id.Prefix = (Identifier)expression;
            id.SourceContext.StartPos = expression.SourceContext.StartPos;
            expression = id;
            if (this.currentToken != Token.EndOfFile)
              this.GetNextToken();
          }else if (this.currentToken == Token.Lambda){
            Parameter par = new Parameter((Identifier)expression, null);
            par.SourceContext = expression.SourceContext;
            return this.ParseLambdaExpression(par.SourceContext, new ParameterList(par), followers);
          }
          break;
        case Token.Null:
          expression = new Literal(null, null, sctx);
          this.GetNextToken();
          break;
        case Token.True:
          expression = new Literal(true, null, sctx);
          this.GetNextToken();
          break;
        case Token.False:
          expression = new Literal(false, null, sctx);
          this.GetNextToken();
          break;
        case Token.CharLiteral:
          expression = new Literal(this.scanner.charLiteralValue, null, sctx);
          this.GetNextToken();
          break;
        case Token.HexLiteral:
          expression = this.ParseHexLiteral();
          break;
        case Token.IntegerLiteral:
          expression = this.ParseIntegerLiteral();
          break;
        case Token.RealLiteral:
          expression = this.ParseRealLiteral();
          break;
        case Token.StringLiteral:
          expression = this.scanner.GetStringLiteral();
          this.GetNextToken();
          break;
        case Token.This:
          expression = new This(sctx, false);
          if (this.sink != null) {
            this.sink.StartName(expression);
          }
          this.GetNextToken();
          if (this.currentToken == Token.LeftParenthesis
            && (this.inInstanceConstructor==BaseOrThisCallKind.None
            || this.inInstanceConstructor==BaseOrThisCallKind.InCtorBodyThisSeen)){
            QualifiedIdentifier thisCons = new QualifiedIdentifier(expression, StandardIds.Ctor, this.scanner.CurrentSourceContext);
            MethodCall thisConstructorCall = new MethodCall(thisCons, null, NodeType.Call);
            thisConstructorCall.SourceContext = sctx;
            SourceContext lpCtx = this.scanner.CurrentSourceContext;
            this.Skip(Token.LeftParenthesis);
            thisConstructorCall.Operands = this.ParseArgumentList(followers|Token.LeftBrace|Token.Semicolon, lpCtx, out thisConstructorCall.SourceContext.EndPos);
            expression = thisConstructorCall;
            this.inInstanceConstructor=BaseOrThisCallKind.InCtorBodyThisSeen;
            goto done;
          }
          break;
        case Token.Base:
          Base ba = new Base(sctx, false);
          expression = ba;
          if (this.sink != null) {
            this.sink.StartName(expression);
          }
          this.GetNextToken();
          if (this.currentToken == Token.Semicolon &&
            (this.inInstanceConstructor == BaseOrThisCallKind.ColonThisOrBaseSeen
            || this.inInstanceConstructor == BaseOrThisCallKind.None)) {
            // When there are non-null fields, then the base ctor call can happen only after they are
            // initialized.
            // In Spec#, we allow a base ctor call in the body of the ctor. But if someone is using
            // the C# comment convention, then they cannot do that.
            // So allow "base;" as a marker to indicate where the base ctor call should happen.
            // There may be an explicit "colon base call" or it may be implicit.
            //
            // Just leave expression as a bare "Base" node; later pipeline stages will all have
            // to ignore it. Mark the current ctor as having (at least) one of these bad boys
            // in it.
            ba.UsedAsMarker = true;
            this.currentCtor.ContainsBaseMarkerBecauseOfNonNullFields = true;
            goto done;
          }
          if (this.currentToken == Token.LeftParenthesis
            && (this.inInstanceConstructor==BaseOrThisCallKind.None
              || this.inInstanceConstructor==BaseOrThisCallKind.InCtorBodyBaseSeen)){
            QualifiedIdentifier supCons = new QualifiedIdentifier(expression, StandardIds.Ctor, this.scanner.CurrentSourceContext);
            MethodCall superConstructorCall = new MethodCall(supCons, null, NodeType.Call);
            superConstructorCall.SourceContext = sctx;
            SourceContext lpCtx = this.scanner.CurrentSourceContext;
            this.Skip(Token.LeftParenthesis);
            superConstructorCall.Operands = this.ParseArgumentList(followers|Token.LeftBrace|Token.Semicolon, lpCtx, out superConstructorCall.SourceContext.EndPos);
            expression = superConstructorCall;
            this.inInstanceConstructor=BaseOrThisCallKind.InCtorBodyBaseSeen;
            goto done;
          }
          break;
        case Token.Typeof:
        case Token.Sizeof:
        case Token.Default:{
          //if (this.currentToken == Token.Sizeof && !this.inUnsafeCode)
            //this.HandleError(Error.SizeofUnsafe);
          UnaryExpression uex = new UnaryExpression(null,
            this.currentToken == Token.Typeof ? NodeType.Typeof : this.currentToken == Token.Sizeof ? NodeType.Sizeof : NodeType.DefaultValue);
          uex.SourceContext = sctx;
          this.GetNextToken();
          this.Skip(Token.LeftParenthesis);
          TypeNode t = null;
          if (this.currentToken == Token.Void && uex.NodeType == NodeType.Typeof){
            t = this.TypeExpressionFor(Token.Void); this.GetNextToken();
          }else
            t = this.ParseTypeExpression(null, followers|Token.RightParenthesis, false, false, uex.NodeType == NodeType.Typeof);
          if (t == null){this.SkipTo(followers); return null;}
          uex.Operand = new MemberBinding(null, t, t.SourceContext, null);
          uex.Operand.SourceContext = t.SourceContext;
          uex.SourceContext.EndPos = this.scanner.endPos;
          this.Skip(Token.RightParenthesis);
          expression = uex;
          break;}
        case Token.Stackalloc:{
          this.GetNextToken();
          TypeNode elementType = this.ParseBaseTypeExpression(null, followers|Token.LeftBracket, false, false);
          if (elementType == null){this.SkipTo(followers); return null;}
          Token openingDelimiter = this.currentToken;
          if (this.currentToken != Token.LeftBracket){
            this.HandleError(Error.BadStackAllocExpr);
            if (this.currentToken == Token.LeftParenthesis) this.GetNextToken();
          }else
            this.GetNextToken();
          Expression numElements = this.ParseExpression(followers|Token.RightBracket|Token.RightParenthesis);
          sctx.EndPos = this.scanner.endPos;
          if (this.currentToken == Token.RightParenthesis && openingDelimiter == Token.LeftParenthesis)
            this.GetNextToken();
          else
            this.Skip(Token.RightBracket);
          this.SkipTo(followers);
          return new StackAlloc(elementType, numElements, sctx);}
        case Token.Checked:
        case Token.Unchecked:
          //TODO: use NodeType.SkipCheck and NodeType.EnforceCheck
          Block b = new Block(new StatementList(1), this.currentToken == Token.Checked, this.currentToken == Token.Unchecked, this.inUnsafeCode);
          b.SourceContext = sctx;
          this.GetNextToken();
          this.Skip(Token.LeftParenthesis);
          b.Statements.Add(new ExpressionStatement(this.ParseExpression(followers|Token.RightParenthesis)));
          this.Skip(Token.RightParenthesis);
          expression = new BlockExpression(b);
          expression.SourceContext = b.SourceContext;
          break;
        case Token.RefType:{
          this.GetNextToken();
          this.Skip(Token.LeftParenthesis);
          Expression e = this.ParseExpression(followers|Token.RightParenthesis);
          this.Skip(Token.RightParenthesis);
          expression = new RefTypeExpression(e, sctx);
          break;
        }
        case Token.RefValue:{
          this.GetNextToken();
          this.Skip(Token.LeftParenthesis);
          Expression e = this.ParseExpression(followers|Token.Comma);
          this.Skip(Token.Comma);
          TypeNode te = this.ParseTypeOrFunctionTypeExpression(followers|Token.RightParenthesis, false, true);
          Expression operand2 = new MemberBinding(null, te);
          if (te is TypeExpression)
            operand2.SourceContext = te.SourceContext;
          else
            operand2.SourceContext = sctx;
          this.Skip(Token.RightParenthesis);
          expression = new RefValueExpression(e, operand2, sctx);
          break;
        }
        case Token.Bool:
        case Token.Decimal:
        case Token.Sbyte:
        case Token.Byte:
        case Token.Short:
        case Token.Ushort:
        case Token.Int:
        case Token.Uint:
        case Token.Long:
        case Token.Ulong:
        case Token.Char:
        case Token.Float:
        case Token.Double:
        case Token.Object:
        case Token.String:
          MemberBinding mb = new MemberBinding(null, this.TypeExpressionFor(this.currentToken), sctx);
          this.GetNextToken();
          expression = this.ParseIndexerCallOrSelector(mb, followers);
          goto done;
        case Token.LeftParenthesis:
          expression = this.ParseParenthesizedExpression(followers|Token.Dot|Token.LeftBracket|Token.Arrow, true);
          break;
        default:
          if (Parser.IdentifierOrNonReservedKeyword[this.currentToken]) goto case Token.Identifier;
          if (Parser.InfixOperators[this.currentToken]){
            this.HandleError(Error.InvalidExprTerm, this.scanner.GetTokenSource());
            this.GetNextToken();
          }else
            this.SkipTo(followers|Parser.PrimaryStart, Error.InvalidExprTerm, this.scanner.GetTokenSource());
          if (Parser.PrimaryStart[this.currentToken]) return this.ParsePrimaryExpression(followers);
          goto done;
      }
      if (expression is Base && this.currentToken != Token.Dot && this.currentToken != Token.LeftBracket){
        this.HandleError(expression.SourceContext, Error.BaseIllegal);
        expression = null;
      }

      expression = this.ParseIndexerCallOrSelector(expression, followers|Token.AddOne|Token.SubtractOne);
      for(;;){
        switch(this.currentToken){
          case Token.AddOne:
          case Token.SubtractOne:
            SourceContext ctx = expression.SourceContext;
            ctx.EndPos = this.scanner.endPos;
            PostfixExpression pex = new PostfixExpression(expression, Parser.ConvertToBinaryNodeType(this.currentToken), ctx);
            this.GetNextToken();
            expression = pex;
            break;
          case Token.Dot:
            expression = this.ParseIndexerCallOrSelector(expression, followers|Token.AddOne|Token.SubtractOne);
            break;
          default:
            goto done;
        }
      }
      done:
        this.SkipTo(followers);
      return expression;
    }
示例#2
0
 private void ParseConstructor(TypeNode parentType, AttributeList attributes, TokenList modifierTokens,
   SourceContextList modifierContexts, object sctx, SourceContext idCtx, TokenSet followers){
   InstanceInitializer c = new InstanceInitializer(parentType, attributes, null, null, this.TypeExpressionFor(Token.Void));
   this.currentCtor = c;
   c.Name = new Identifier(".ctor", idCtx);
   MethodFlags flags = this.GetMethodFlags(modifierTokens, modifierContexts, parentType, c);
   if ((flags & MethodFlags.Static) != 0){
     this.currentCtor = null; // Can you call "base" in a static ctor?
     this.ParseStaticConstructor(parentType, attributes, modifierTokens, modifierContexts, flags, sctx, idCtx, followers);
     return;
   }
   parentType.Members.Add(c);
   c.Flags |= flags|MethodFlags.HideBySig;
   c.Parameters = this.ParseParameters(Token.RightParenthesis, followers|Token.LeftBrace|Token.Semicolon|Token.Colon|Parser.ContractStart|Token.Where);
   c.HasCompilerGeneratedSignature = false;
   c.Documentation = this.LastDocComment;
   QualifiedIdentifier supCons = new QualifiedIdentifier(new Base(), StandardIds.Ctor, this.scanner.CurrentSourceContext);
   MethodCall superConstructorCall = new MethodCall(supCons, null, NodeType.Call);
   superConstructorCall.SourceContext = this.scanner.CurrentSourceContext;
   StatementList slist = new StatementList();
   Block body = new Block(slist, this.insideCheckedBlock, this.insideUncheckedBlock, this.inUnsafeCode);
   body.SourceContext = this.scanner.CurrentSourceContext;
   Block iblock = new Block(new StatementList(), this.insideCheckedBlock, this.insideUncheckedBlock, this.inUnsafeCode);
   if (this.currentToken == Token.Colon){
     this.GetNextToken();
     bool savedParsingStatement = this.parsingStatement;
     this.parsingStatement = true;
     superConstructorCall.SourceContext = this.scanner.CurrentSourceContext;
     supCons.SourceContext = this.scanner.CurrentSourceContext;
     bool init = false;
     this.inInstanceConstructor = BaseOrThisCallKind.ColonThisOrBaseSeen;
     if (this.currentToken == Token.This){
       if (this.sink != null) this.sink.StartName(new Identifier(".ctor", this.scanner.CurrentSourceContext));
       supCons.Qualifier = new This(this.scanner.CurrentSourceContext, true);
       this.GetNextToken();
     }else if (this.currentToken == Token.Base){
       if (parentType.IsValueType)
         this.HandleError(Error.StructWithBaseConstructorCall, new ErrorHandler(this.errors).GetMemberSignature(c));
       else if (this.sink != null)
         this.sink.StartName(new Identifier(".ctor", this.scanner.CurrentSourceContext));
       supCons.Qualifier = new Base(this.scanner.CurrentSourceContext, true);
       this.GetNextToken();
     }else{
       if (!init)
         this.SkipTo(followers|Token.LeftBrace|Token.Semicolon|Parser.ContractStart|Token.Where, Error.ThisOrBaseExpected);
       if (this.currentToken != Token.EndOfFile) this.parsingStatement = savedParsingStatement;
       goto parseBody;
     }
     SourceContext lpCtx = this.scanner.CurrentSourceContext;
     this.Skip(Token.LeftParenthesis);
     superConstructorCall.Operands = this.ParseArgumentList(followers|Token.LeftBrace|Token.Semicolon|Parser.ContractStart|Token.Where, lpCtx, out superConstructorCall.SourceContext.EndPos);
     if (this.currentToken != Token.EndOfFile) this.parsingStatement = savedParsingStatement;
   } else {
     // no colon ==> no "base" or "this" before body of ctor
     if (! parentType.IsValueType)
       this.inInstanceConstructor = BaseOrThisCallKind.None;
   }
 parseBody:
   superConstructorCall.SourceContext.EndPos = this.scanner.endPos;
   supCons.SourceContext.EndPos = this.scanner.endPos;
   bool swallowedSemicolonAlready = false;
   this.ParseMethodContract(c, followers|Token.LeftBrace|Token.Semicolon, ref swallowedSemicolonAlready);
   Block b;
   if (this.parsingContractAssembly)
     b = this.ParseBody(c, sctx, followers, swallowedSemicolonAlready); // only allow semicolon body in contract assemblies
   else
     b = this.ParseBody(c, sctx, followers);
   slist.Add(iblock);
   c.IsDeferringConstructor = supCons.Qualifier is This || this.inInstanceConstructor == BaseOrThisCallKind.InCtorBodyThisSeen;
   if (!c.IsDeferringConstructor){
     slist.Add(new FieldInitializerBlock(parentType,false));
   }
   Block baseOrDeferringCallBlock = new Block(new StatementList(1));
   c.BaseOrDefferingCallBlock = baseOrDeferringCallBlock;
   slist.Add(baseOrDeferringCallBlock);
   if (this.inInstanceConstructor == BaseOrThisCallKind.None || this.inInstanceConstructor == BaseOrThisCallKind.ColonThisOrBaseSeen){
     if (!(parentType.IsValueType || this.TypeIsSystemObject(parentType)) || supCons.Qualifier is This)
       baseOrDeferringCallBlock.Statements.Add(new ExpressionStatement(superConstructorCall, superConstructorCall.SourceContext));
   }
   if (b != null){
     slist.Add(b);
     body.SourceContext.EndPos = b.SourceContext.EndPos;
     if ((c.Flags & MethodFlags.PInvokeImpl) != 0 && b.Statements != null && b.Statements.Count > 0)
       body = null;
     else if (this.omitBodies)
       b.Statements = null;
   }else if ((c.Flags & MethodFlags.PInvokeImpl) != 0)
     body = null;
   c.Body = body;
   this.inInstanceConstructor = BaseOrThisCallKind.Disallowed;
   this.currentCtor = null;
 }