Ejemplo n.º 1
0
 private void ParseProperty(TypeNode parentType, AttributeList attributes, TokenList modifierTokens,
   SourceContextList modifierContexts, object sctx, TypeNode type, TypeNode interfaceType, Identifier name, TokenSet followers){
   SourceContext ctx = (SourceContext)sctx;
   ctx.EndPos = this.scanner.endPos;
   bool isIndexer = this.currentToken == Token.This && name.UniqueIdKey == StandardIds.Item.UniqueIdKey;
   Debug.Assert(this.currentToken == Token.LeftBrace || isIndexer);
   this.GetNextToken();
   ParameterList paramList = null;
   if (isIndexer){
     if (interfaceType == null){
       AttributeNode defaultMember = new AttributeNode();
       defaultMember.Constructor = new Literal(TypeExpressionFor("System", "Reflection", "DefaultMemberAttribute"));
       defaultMember.Expressions = new ExpressionList(1);
       defaultMember.Expressions.Add(new Literal("Item"));
       if (parentType.Attributes == null) parentType.Attributes = new AttributeList(1);
       parentType.Attributes.Add(defaultMember);
     }
     paramList = this.ParseParameters(Token.RightBracket, followers|Token.LeftBrace);
     this.Skip(Token.LeftBrace);
   }
   Property p = new Property(parentType, attributes, PropertyFlags.None, name, null, null);
   parentType.Members.Add(p);
   p.SourceContext = ctx;
   p.Documentation = this.LastDocComment;
   p.Type = p.TypeExpression = type;
   MethodFlags mflags;
   if (interfaceType != null){
     p.ImplementedTypeExpressions = p.ImplementedTypes = new TypeNodeList(interfaceType);
     mflags = MethodFlags.Private|MethodFlags.HideBySig|MethodFlags.NewSlot|MethodFlags.Final|MethodFlags.Virtual|MethodFlags.SpecialName;
     for (int i = 0, n = modifierContexts == null ? 0 : modifierContexts.Length; i < n; i++) {
       if (modifierTokens[i] == Token.Extern)
         mflags |= MethodFlags.PInvokeImpl;
       else if (modifierTokens[i] == Token.Unsafe) {
         if (!this.allowUnsafeCode) {
           this.allowUnsafeCode = true;
           this.HandleError(modifierContexts[i], Error.IllegalUnsafe);
         }
         this.inUnsafeCode = true;
       } else
         this.HandleError(modifierContexts[i], Error.InvalidModifier, modifierContexts[i].SourceText);
     }
   }else
     mflags = this.GetMethodFlags(modifierTokens, modifierContexts, parentType, p)|MethodFlags.SpecialName;
   if ((mflags & MethodFlags.Static) != 0 && parentType is Interface){
     this.HandleError(name.SourceContext, Error.InvalidModifier, "static");
     mflags &= ~MethodFlags.Static;
     mflags |= MethodFlags.Abstract;
   }
   TokenSet followersOrRightBrace = followers|Token.RightBrace;
   bool accessorModifiersAlreadySpecified = false;
   MethodFlags accessorFlags = mflags;
   while (Parser.GetOrLeftBracketOrSetOrModifier[this.currentToken]){
     SourceContext sc = this.scanner.CurrentSourceContext;
     AttributeList accessorAttrs = this.ParseAttributes(null, followers|Token.Get|Token.Set|Token.LeftBrace);
     switch (this.currentToken){
       case Token.Get:{
         if (p.Getter != null)
           this.HandleError(Error.DuplicateAccessor);
         SourceContext scntx = this.scanner.CurrentSourceContext;
         this.GetNextToken();
         Method m = new Method(parentType, accessorAttrs, new Identifier("get_"+name.ToString()), paramList, type, null);
         m.SourceContext = sc;
         m.ReturnTypeExpression = type;
         m.Name.SourceContext = scntx;
         if ((accessorFlags & MethodFlags.Static) == 0)
           m.CallingConvention = CallingConventionFlags.HasThis;
         parentType.Members.Add(m);
         m.Flags = accessorFlags|MethodFlags.HideBySig;
         if (interfaceType != null)
           m.ImplementedTypeExpressions = m.ImplementedTypes = new TypeNodeList(interfaceType);
         bool swallowedSemicolonAlready = false;
         bool bodyAllowed = true;
         if (this.currentToken == Token.Semicolon){
           m.SourceContext.EndPos = this.scanner.endPos;
           this.GetNextToken();
           bodyAllowed = false;
           swallowedSemicolonAlready = true;
         }
         this.ParseMethodContract(m, followers|Token.LeftBrace|Token.Semicolon, ref swallowedSemicolonAlready);
         if (bodyAllowed)
           m.Body = this.ParseBody(m, sc, followersOrRightBrace|Token.Set, swallowedSemicolonAlready);
         else if (!swallowedSemicolonAlready)
           this.SkipSemiColon(followersOrRightBrace|Token.Set);
         p.Getter = m;
         m.DeclaringMember = p;
         accessorFlags = mflags;
         break;}
       case Token.Set:{
         if (p.Setter != null)
           this.HandleError(Error.DuplicateAccessor);
         SourceContext scntx = this.scanner.CurrentSourceContext;
         this.GetNextToken();
         ParameterList parList = new ParameterList();
         if (paramList != null)
           for (int i = 0, n = paramList.Count; i < n; i++) parList.Add((Parameter)paramList[i].Clone());
         parList.Add(new Parameter(null, ParameterFlags.None, Identifier.For("value"), type, null, null));
         Method m = new Method(parentType, accessorAttrs, new Identifier("set_"+name.ToString()), parList, this.TypeExpressionFor(Token.Void), null);
         m.SourceContext = sc;
         m.Name.SourceContext = scntx;
         if ((accessorFlags & MethodFlags.Static) == 0)
           m.CallingConvention = CallingConventionFlags.HasThis;
         parentType.Members.Add(m);
         m.Flags = accessorFlags|MethodFlags.HideBySig;
         if (interfaceType != null)
           m.ImplementedTypeExpressions = m.ImplementedTypes = new TypeNodeList(interfaceType);
         bool swallowedSemicolonAlready = false;
         bool bodyAllowed = true;
         if (this.currentToken == Token.Semicolon) {
           m.SourceContext.EndPos = this.scanner.endPos;
           this.GetNextToken();
           bodyAllowed = false;
           swallowedSemicolonAlready = true;
         }
         this.ParseMethodContract(m, followers|Token.LeftBrace|Token.Semicolon, ref swallowedSemicolonAlready);
         if (bodyAllowed)
           m.Body = this.ParseBody(m, sc, followersOrRightBrace|Token.Get, swallowedSemicolonAlready);
         else if (!swallowedSemicolonAlready)
           this.SkipSemiColon(followersOrRightBrace|Token.Get);
         p.Setter = m;
         m.DeclaringMember = p;
         accessorFlags = mflags;
         break;}
       case Token.Protected:
       case Token.Internal:
       case Token.Private:
         if (parentType is Interface || interfaceType != null || accessorModifiersAlreadySpecified)
           goto case Token.New;
         accessorFlags = this.ParseAccessorModifiers(mflags);
         accessorModifiersAlreadySpecified = true;
         break;
       case Token.Public:
       case Token.New:
       case Token.Abstract:
       case Token.Sealed:
       case Token.Static:
       case Token.Readonly:
       case Token.Volatile:
       case Token.Virtual:
       case Token.Override:
       case Token.Extern:
       case Token.Unsafe:
         this.HandleError(Error.NoModifiersOnAccessor);
         this.GetNextToken();
         break;
       default:
         this.SkipTo(followersOrRightBrace, Error.GetOrSetExpected);
         break;
     }
   }
   p.SourceContext.EndPos = this.scanner.endPos;
   Error e = Error.GetOrSetExpected;
   if (p.Getter == null && p.Setter == null) p.Parameters = paramList;
   if (p.Getter != null && p.Setter != null) e = Error.ExpectedRightBrace;
   if ((p.Getter == null || p.Setter == null) && this.sink != null && this.currentToken == Token.Identifier){
     p.SourceContext.EndPos = this.scanner.startPos-1;
     KeywordCompletionList keywords;
     if (p.Getter != null)
       keywords = new KeywordCompletionList(this.scanner.GetIdentifier(), new KeywordCompletion("set"));
     else if (p.Setter != null)
       keywords = new KeywordCompletionList(this.scanner.GetIdentifier(), new KeywordCompletion("get"));
     else
       keywords = new KeywordCompletionList(this.scanner.GetIdentifier(), new KeywordCompletion("get"), new KeywordCompletion("set"));
     parentType.Members.Add(keywords);
     this.GetNextToken();
     this.SkipTo(followers);
     return;
   }
   this.ParseBracket(ctx, Token.RightBrace, followers, e);
 }
Ejemplo n.º 2
0
 private void ParseEvent(TypeNode parentType, AttributeList attributes, TokenList modifierTokens,
   SourceContextList modifierContexts, object sctx, TokenSet followers){
   Debug.Assert(this.currentToken == Token.Event);
   this.GetNextToken();
   Event e = new Event(parentType, attributes, EventFlags.None, null, null, null, null, null);
   e.DeclaringType = parentType;
   e.Documentation = this.LastDocComment;
   TypeNode t = this.ParseTypeExpression(Identifier.Empty, followers|Parser.IdentifierOrNonReservedKeyword);
   //REVIEW: allow events with anonymous delegate type?
   e.HandlerType = e.HandlerTypeExpression = t;
   TypeExpression interfaceType = null;
   Identifier id = this.scanner.GetIdentifier();
   this.SkipIdentifierOrNonReservedKeyword();
   TypeNodeList templateArguments = null;
   int endPos = 0, arity = 0;
   while (this.currentToken == Token.Dot || this.currentToken == Token.LessThan) {
     if (interfaceType == null && this.ExplicitInterfaceImplementationIsAllowable(parentType, id)) {
       for (int i = 0, n = modifierContexts == null ? 0 : modifierContexts.Length; i < n; i++){
         this.HandleError(modifierContexts[i], Error.InvalidModifier, modifierContexts[i].SourceText);
         modifierTokens = new TokenList(0);
       }
     }
     TypeExpression intfExpr = interfaceType;
     if (intfExpr == null) {
       intfExpr = new TypeExpression(id, id.SourceContext);
     } else if( templateArguments == null) {
       SourceContext ctx = intfExpr.Expression.SourceContext;
       ctx.EndPos = id.SourceContext.EndPos;
       intfExpr.Expression = new QualifiedIdentifier(intfExpr.Expression, id, ctx);
     }
     if (templateArguments != null) {
       intfExpr.TemplateArguments = templateArguments;
       intfExpr.SourceContext.EndPos = endPos;
     }
     if (this.currentToken == Token.LessThan) {
       templateArguments = this.ParseTypeArguments(true, false, followers | Token.Dot | Token.LeftParenthesis | Token.LeftBrace, out endPos, out arity);
     } else {  //  Dot
       templateArguments = null;
       this.GetNextToken();
       id = this.scanner.GetIdentifier();
       this.SkipIdentifierOrNonReservedKeyword();
       if (intfExpr == null) id.SourceContext.Document = null;
     }
     interfaceType = intfExpr;
   }
   e.Name = id;
   MethodFlags mflags = this.GetMethodFlags(modifierTokens, modifierContexts, parentType, e);
   if ((mflags & MethodFlags.Static) != 0 && parentType is Interface){
     this.HandleError(id.SourceContext, Error.InvalidModifier, "static");
     mflags &= ~MethodFlags.Static;
     mflags |= MethodFlags.Abstract;
   }
   e.HandlerFlags = mflags|MethodFlags.SpecialName;
   bool hasAccessors = this.currentToken == Token.LeftBrace || interfaceType != null;
   if (hasAccessors){
     if (interfaceType != null){
       e.ImplementedTypeExpressions = e.ImplementedTypes = new TypeNodeList(interfaceType);
       if (this.currentToken != Token.LeftBrace){
         this.HandleError(Error.ExplicitEventFieldImpl);
         hasAccessors = false;
         goto nextDeclarator;
       }
     }
     this.Skip(Token.LeftBrace);
     TokenSet followersOrRightBrace = followers|Token.RightBrace;
     bool alreadyGivenAddOrRemoveExpectedError = false;
     bool alreadyComplainedAboutAccessors = false;
     for(;;){
       SourceContext sc = this.scanner.CurrentSourceContext;
       AttributeList accessorAttrs = this.ParseAttributes(null, followers|Parser.AddOrRemoveOrModifier|Token.LeftBrace);
       switch (this.currentToken){
         case Token.Add:
           if (parentType is Interface && !alreadyComplainedAboutAccessors){
             this.HandleError(Error.EventPropertyInInterface, parentType.FullName+"."+id);
             alreadyComplainedAboutAccessors = true;
           }else if (e.HandlerAdder != null)
             this.HandleError(Error.DuplicateAccessor);
           SourceContext scntx = this.scanner.CurrentSourceContext;
           this.GetNextToken();
           ParameterList parList = new ParameterList();
           parList.Add(new Parameter(null, ParameterFlags.None, StandardIds.Value, t, null, null));
           Method m = new Method(parentType, accessorAttrs, new Identifier("add_"+id.ToString()), parList, this.TypeExpressionFor(Token.Void), null);
           m.HidesBaseClassMember = e.HidesBaseClassMember;
           m.OverridesBaseClassMember = e.OverridesBaseClassMember;
           m.Name.SourceContext = scntx;
           if ((mflags & MethodFlags.Static) == 0)
             m.CallingConvention = CallingConventionFlags.HasThis;
           m.Flags = mflags|MethodFlags.HideBySig|MethodFlags.SpecialName;
           if (interfaceType != null){
             m.Flags = MethodFlags.Private|MethodFlags.HideBySig|MethodFlags.NewSlot|MethodFlags.Final|MethodFlags.Virtual|MethodFlags.SpecialName;
             m.ImplementedTypeExpressions = m.ImplementedTypes = new TypeNodeList(interfaceType);
           }
           if (this.currentToken != Token.LeftBrace){
             this.SkipTo(followersOrRightBrace|Token.Remove, Error.AddRemoveMustHaveBody);
             alreadyGivenAddOrRemoveExpectedError = true;
           }else
             m.Body = this.ParseBody(m, sc, followersOrRightBrace|Token.Remove);
           if (!(parentType is Interface)){
             e.HandlerAdder = m;
             m.DeclaringMember = e;
             parentType.Members.Add(m);
           }
           continue;
         case Token.Remove:
           if (parentType is Interface && !alreadyComplainedAboutAccessors){
             this.HandleError(Error.EventPropertyInInterface, parentType.FullName+"."+id);
             alreadyComplainedAboutAccessors = true;
           }else if (e.HandlerRemover != null)
             this.HandleError(Error.DuplicateAccessor);
           scntx = this.scanner.CurrentSourceContext;
           this.GetNextToken();
           parList = new ParameterList();
           parList.Add(new Parameter(null, ParameterFlags.None, StandardIds.Value, t, null, null));
           m = new Method(parentType, accessorAttrs, new Identifier("remove_"+id.ToString()), parList, this.TypeExpressionFor(Token.Void), null);
           m.HidesBaseClassMember = e.HidesBaseClassMember;
           m.OverridesBaseClassMember = e.OverridesBaseClassMember;
           m.Name.SourceContext = scntx;
           if ((mflags & MethodFlags.Static) == 0)
             m.CallingConvention = CallingConventionFlags.HasThis;
           m.Flags = mflags|MethodFlags.HideBySig|MethodFlags.SpecialName;
           if (interfaceType != null){
             m.Flags = MethodFlags.Private|MethodFlags.HideBySig|MethodFlags.NewSlot|MethodFlags.Final|MethodFlags.Virtual|MethodFlags.SpecialName;
             m.ImplementedTypeExpressions = m.ImplementedTypes = new TypeNodeList(interfaceType);
           }
           if (this.currentToken != Token.LeftBrace){
             this.SkipTo(followersOrRightBrace|Token.Add, Error.AddRemoveMustHaveBody);
             alreadyGivenAddOrRemoveExpectedError = true;
           }else
             m.Body = this.ParseBody(m, sc, followersOrRightBrace|Token.Add);
           if (!(parentType is Interface)){
             e.HandlerRemover = m;
             m.DeclaringMember = e;
             parentType.Members.Add(m);
           }
           continue;
         case Token.New:
         case Token.Public:
         case Token.Protected:
         case Token.Internal:
         case Token.Private:
         case Token.Abstract:
         case Token.Sealed:
         case Token.Static:
         case Token.Readonly:
         case Token.Volatile:
         case Token.Virtual:
         case Token.Override:
         case Token.Extern:
         case Token.Unsafe:
           this.HandleError(Error.NoModifiersOnAccessor);
           this.GetNextToken();
           break;
         default:
           if ((e.HandlerAdder == null || e.HandlerRemover == null) && this.sink != null && this.currentToken == Token.Identifier && this.scanner.endPos == this.scanner.maxPos){
             e.SourceContext.EndPos = this.scanner.startPos;
             KeywordCompletionList keywords;
             if (e.HandlerAdder != null)
               keywords = new KeywordCompletionList(this.scanner.GetIdentifier(), new KeywordCompletion("remove"));
             else if (e.HandlerRemover != null)
               keywords = new KeywordCompletionList(this.scanner.GetIdentifier(), new KeywordCompletion("add"));
             else
               keywords = new KeywordCompletionList(this.scanner.GetIdentifier(), new KeywordCompletion("add"), new KeywordCompletion("remove"));
             parentType.Members.Add(keywords);
             this.GetNextToken();
           }
           if (!alreadyGivenAddOrRemoveExpectedError && !alreadyComplainedAboutAccessors && (e.HandlerAdder == null || e.HandlerRemover == null)) {
             if (this.currentToken == Token.RightBrace)
               this.HandleError(id.SourceContext, Error.EventNeedsBothAccessors, parentType.FullName+"."+id.Name);
             else
               this.HandleError(Error.AddOrRemoveExpected);
             alreadyGivenAddOrRemoveExpectedError = true;
             if (!(Parser.EndOfFile|Token.LeftBrace|Token.RightBrace)[this.currentToken])
               this.GetNextToken();
             this.SkipTo(followersOrRightBrace|Token.LeftBrace, Error.None);
             if (this.currentToken == Token.LeftBrace){
               this.ParseBlock(followersOrRightBrace|Token.Add|Token.Remove);
               continue;
             }
           }
           break;
       }
       break;
     }
     this.Skip(Token.RightBrace); //TODO: brace matching
   }
   nextDeclarator:
     e.Name = id;
   e.SourceContext = (SourceContext)sctx;
   e.SourceContext.EndPos = this.scanner.endPos;
   parentType.Members.Add(e);
   if (!hasAccessors){
     switch(this.currentToken){
       case Token.Assign:
         this.GetNextToken();
         e.InitialHandler = this.ParseExpression(followers|Token.Semicolon);
         if (parentType is Interface && e.InitialHandler != null){
           this.HandleError(e.InitialHandler.SourceContext, Error.InterfaceEventInitializer, parentType.FullName+"."+id);
           e.InitialHandler = null;
         }
         if (this.currentToken == Token.Comma)
           goto case Token.Comma;
         else
           goto default;
       case Token.Comma:
         this.GetNextToken();
         id = this.scanner.GetIdentifier();
         this.SkipIdentifierOrNonReservedKeyword(); //REVIEW: allow interface name?
         e = new Event(parentType, attributes, (EventFlags)0, null, null, null, null, null);
         e.HandlerFlags = mflags;
         e.HandlerType = e.HandlerTypeExpression = t;
         goto nextDeclarator;
       default:
         this.Skip(Token.Semicolon);
         break;
     }
   }
 }