예제 #1
0
 private void ParseOperator(TypeNode parentType, AttributeList attributes, TokenList modifierTokens,
   SourceContextList modifierContexts, TypeNode resultType, object sctx, TokenSet followers){
   if (parentType is Interface)
     this.HandleError(Error.InterfacesCantContainOperators);
   Identifier opName = null;
   SourceContext ctx = this.scanner.CurrentSourceContext;
   SourceContext symCtx = ctx;
   bool canBeBinary = false;
   bool canBeUnary = false;
   switch(this.currentToken){
     case Token.Explicit:
       opName = new Identifier("op_Explicit", ctx);
       canBeUnary = true;
       this.GetNextToken();
       opName.SourceContext.EndPos = this.scanner.endPos;
       this.Skip(Token.Operator);
       if (resultType != null && this.currentToken == Token.LeftParenthesis)
         this.HandleError(opName.SourceContext, Error.BadOperatorSyntax, "explicit");
       else
         resultType = this.ParseTypeExpression(null, followers|Token.LeftParenthesis);
       break;
     case Token.Implicit:
       opName = new Identifier("op_Implicit", ctx);
       canBeUnary = true;
       this.GetNextToken();
       opName.SourceContext.EndPos = this.scanner.endPos;
       this.Skip(Token.Operator);
       if (resultType != null && this.currentToken == Token.LeftParenthesis)
         this.HandleError(opName.SourceContext, Error.BadOperatorSyntax, "implicit");
       else
         resultType = this.ParseTypeExpression(null, followers|Token.LeftParenthesis);
       break;
     case Token.Operator:{
       this.GetNextToken();
       symCtx = this.scanner.CurrentSourceContext;
       SourceContext opCtxt = ctx;
       opCtxt.EndPos = this.scanner.endPos;
       switch (this.currentToken){
         case Token.Plus:
           canBeBinary = true;
           canBeUnary = true;
           opName = new Identifier("op_Addition", opCtxt);
           break;
         case Token.Subtract:
           canBeBinary = true;
           canBeUnary = true;
           opName = new Identifier("op_Subtraction", opCtxt);
           break;
         case Token.Multiply:
           canBeBinary = true;
           opName = new Identifier("op_Multiply", opCtxt);
           break;
         case Token.Divide:
           canBeBinary = true;
           opName = new Identifier("op_Division", opCtxt);
           break;
         case Token.Remainder:
           canBeBinary = true;
           opName = new Identifier("op_Modulus", opCtxt);
           break;
         case Token.BitwiseAnd:
           canBeBinary = true;
           opName = new Identifier("op_BitwiseAnd", opCtxt);
           break;
         case Token.BitwiseOr:
           canBeBinary = true;
           opName = new Identifier("op_BitwiseOr", opCtxt);
           break;
         case Token.BitwiseXor:
           canBeBinary = true;
           opName = new Identifier("op_ExclusiveOr", opCtxt);
           break;
         case Token.LeftShift:
           canBeBinary = true;
           opName = new Identifier("op_LeftShift", opCtxt);
           break;
         case Token.RightShift:
           canBeBinary = true;
           opName = new Identifier("op_RightShift", opCtxt);
           break;
         case Token.Equal:
           canBeBinary = true;
           opName = new Identifier("op_Equality", opCtxt);
           break;
         case Token.NotEqual:
           canBeBinary = true;
           opName = new Identifier("op_Inequality", opCtxt);
           break;
         case Token.GreaterThan:
           canBeBinary = true;
           opName = new Identifier("op_GreaterThan", opCtxt);
           break;
         case Token.LessThan:
           canBeBinary = true;
           opName = new Identifier("op_LessThan", opCtxt);
           break;
         case Token.GreaterThanOrEqual:
           canBeBinary = true;
           opName = new Identifier("op_GreaterThanOrEqual", opCtxt);
           break;
         case Token.LessThanOrEqual:
           canBeBinary = true;
           opName = new Identifier("op_LessThanOrEqual", opCtxt);
           break;
         case Token.LogicalNot:
           canBeUnary = true;
           opName = new Identifier("op_LogicalNot", opCtxt);
           break;
         case Token.BitwiseNot:
           canBeUnary = true;
           opName = new Identifier("op_OnesComplement", opCtxt);
           break;
         case Token.AddOne:
           canBeUnary = true;
           opName = new Identifier("op_Increment", opCtxt);
           break;
         case Token.SubtractOne:
           canBeUnary = true;
           opName = new Identifier("op_Decrement", opCtxt);
           break;
         case Token.True:
           canBeUnary = true;
           opName = new Identifier("op_True", opCtxt);
           break;
         case Token.False:
           canBeUnary = true;
           opName = new Identifier("op_False", opCtxt);
           break;
         case Token.Implicit:
           canBeUnary = true;
           opName = new Identifier("op_Implicit", opCtxt);
           this.HandleError(opName.SourceContext, Error.BadOperatorSyntax, "implicit");
           break;
         case Token.Explicit:
           canBeUnary = true;
           opName = new Identifier("op_Explicit", opCtxt);
           this.HandleError(opName.SourceContext, Error.BadOperatorSyntax, "explicit");
           break;
       }
       if (this.currentToken != Token.EndOfFile) this.GetNextToken();
       if (resultType == null){
         this.HandleError(Error.BadOperatorSyntax2, opCtxt.SourceText);
         if (this.currentToken != Token.LeftParenthesis)
           resultType = this.ParseTypeExpression(null, followers|Token.LeftParenthesis);
         else
           resultType = parentType;
       }
       break;}
     default:
       Debug.Assert(false);
       break;
   }
   //Parse the parameter list
   SourceContext pctx = this.scanner.CurrentSourceContext;
   ParameterList parameters = this.ParseParameters(Token.RightParenthesis, followers|Token.LeftBrace|Token.Semicolon|Token.Requires|Token.Modifies|Token.Ensures|Token.Where|Token.Throws);
   switch (parameters.Count){
     case 1:
       if (!canBeUnary)
         this.HandleError(symCtx, Error.OvlUnaryOperatorExpected);
       if (canBeBinary && opName != null){
         if (opName.UniqueIdKey == StandardIds.opAddition.UniqueIdKey) opName = new Identifier("op_UnaryPlus", opName.SourceContext);
         else if (opName.UniqueIdKey == StandardIds.opSubtraction.UniqueIdKey) opName = new Identifier("op_UnaryNegation", opName.SourceContext);
       }
       break;
     case 2:
       if (!canBeBinary)
         if (canBeUnary)
           this.HandleError(pctx, Error.WrongParsForUnaryOp, opName.SourceContext.SourceText);
         else
           this.HandleError(symCtx, Error.OvlBinaryOperatorExpected);
       break;
     default:
       if (canBeBinary)
         this.HandleError(pctx, Error.WrongParsForBinOp, opName.SourceContext.SourceText);
       else if (canBeUnary)
         this.HandleError(pctx, Error.WrongParsForUnaryOp, opName.SourceContext.SourceText);
       else
         this.HandleError(symCtx, Error.OvlBinaryOperatorExpected);
       break;
   }
   ctx.EndPos = this.scanner.endPos;
   MethodFlags flags = MethodFlags.Public;
   if (!(parentType is Interface))
     flags = this.GetOperatorFlags(modifierTokens, modifierContexts, ctx);
   else
     flags |= MethodFlags.SpecialName|MethodFlags.Static;
   Method oper = new Method(parentType, attributes, opName, parameters, resultType, null);
   oper.ReturnTypeExpression = resultType;
   oper.Flags = flags;
   oper.IsUnsafe = this.inUnsafeCode;
   bool swallowedSemicolonAlready = false;
   this.ParseMethodContract(oper, followers|Token.LeftBrace|Token.Semicolon, ref swallowedSemicolonAlready);
   oper.Body = this.ParseBody(oper, sctx, followers, swallowedSemicolonAlready);
   oper.HasCompilerGeneratedSignature = false;
   parentType.Members.Add(oper);
   oper.Documentation = this.LastDocComment;
 }
예제 #2
0
 private void ParseModifiers(TokenList modifierTokens, SourceContextList modifierContexts, bool parsingInterface){
   if (parsingInterface && this.currentToken == Token.New){
     modifierTokens.Add(this.currentToken);
     modifierContexts.Add(this.scanner.CurrentSourceContext);
     this.GetNextToken();
     modifierTokens.Add(Token.Public);
     modifierContexts.Add(this.scanner.CurrentSourceContext);
     modifierTokens.Add(Token.Abstract);
     modifierContexts.Add(this.scanner.CurrentSourceContext);
     return;
   }
   for(;;){
     switch(this.currentToken){
       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:
         if (parsingInterface && this.currentToken != Token.Readonly && this.currentToken != Token.Static)
           modifierTokens.Add(Token.IllegalCharacter);
         else
           modifierTokens.Add(this.currentToken);
         modifierContexts.Add(this.scanner.CurrentSourceContext);
         break;
       case Token.Unsafe:
         this.inUnsafeCode = true;
         modifierTokens.Add(this.currentToken);
         modifierContexts.Add(this.scanner.CurrentSourceContext);
         this.GetNextToken();
         if (this.currentToken == Token.LeftBrace){
           this.HandleError(Error.TypeExpected);
           this.GetNextToken();
           return;
         }
         continue;
       default:
         if (parsingInterface){
           modifierTokens.Add(Token.Public);
           modifierContexts.Add(new SourceContext());
           modifierTokens.Add(Token.Abstract);
           modifierContexts.Add(new SourceContext());
         }
         return;
     }
     this.GetNextToken();
   }
 }
예제 #3
0
 private void ParseStaticConstructor(TypeNode parentType, AttributeList attributes, TokenList modifierTokens,
   SourceContextList modifierContexts, MethodFlags flags, object sctx, SourceContext idCtx, TokenSet followers){
   if (parentType is Interface){
     this.HandleError(idCtx, Error.InterfacesCannotContainConstructors);
   }else{
     for (int i = 0, n = modifierTokens.Length; i < n; i++){
       Token tok = modifierTokens[i];
       if (tok == Token.Static || tok == Token.Extern) continue;
       if (tok == Token.Unsafe){
         if (!this.allowUnsafeCode){
           this.allowUnsafeCode = true;
           this.HandleError(modifierContexts[i], Error.IllegalUnsafe);
         }
         this.inUnsafeCode = true;
         continue;
       }
       this.HandleError(modifierContexts[i], Error.StaticConstructorWithAccessModifiers);
     }
   }
   StaticInitializer c = new StaticInitializer(parentType, attributes,
     new Block(new StatementList(2), this.insideCheckedBlock, this.insideUncheckedBlock, this.inUnsafeCode), this.TypeExpressionFor(Token.Void));
   c.Name = new Identifier(".cctor", idCtx);
   parentType.Members.Add(c);
   c.Flags |= flags;
   c.HasCompilerGeneratedSignature = false;
   ParameterList plist = c.Parameters = this.ParseParameters(Token.RightParenthesis, followers|Token.LeftBrace|Token.Colon);
   if (plist != null && plist.Count > 0){
     this.HandleError(plist[0].SourceContext, Error.StaticConstParam);
     c.Parameters = null;
   }
   if (this.currentToken == Token.Colon){
     SourceContext ctx = this.scanner.CurrentSourceContext;
     this.GetNextToken();
     if (this.currentToken == Token.This || this.currentToken == Token.Base){
       ctx.EndPos = this.scanner.endPos;
       this.GetNextToken();
       if (this.currentToken == Token.LeftParenthesis){
         SourceContext lpCtx = this.scanner.CurrentSourceContext;
         this.Skip(Token.LeftParenthesis);
         this.ParseArgumentList(followers|Token.LeftBrace, lpCtx, out ctx.EndPos);
       }
     }else
       this.SkipTo(followers|Token.LeftBrace, Error.None);
     this.HandleError(ctx, Error.StaticConstructorWithExplicitConstructorCall);
   }
   Block b = this.ParseBody(c, sctx, followers);
   c.Body.Statements.Add(new FieldInitializerBlock(parentType, true));
   c.Body.Statements.Add(b);
 }
예제 #4
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);
 }
예제 #5
0
 private void ParseTypeDeclaration(Namespace ns, TypeNode parentType, AttributeList attributes, TokenList modifierTokens,
   SourceContextList modifierContexts, bool isPartial, SourceContext sctx, TokenSet followers){
   this.ParseTypeDeclaration(ns, parentType, attributes, modifierTokens, modifierContexts, TypeFlags.None, isPartial, sctx, followers);
 }
예제 #6
0
 private MethodFlags GetDestructorFlags(TokenList modifierTokens, SourceContextList modifierContexts, Member destructor){
   MethodFlags result = MethodFlags.Family|MethodFlags.HideBySig|MethodFlags.Virtual;
   int n = modifierTokens.Length;
   if (n == 0) return result;
   int firstNonExtern = -1;
   int secondNonExtern = -1;
   for (int i = 0; i < n; i++){
     switch (modifierTokens[i]){
       case Token.Extern:
         if ((result & MethodFlags.PInvokeImpl) != 0){
           this.HandleError(modifierContexts[i], Error.DuplicateModifier, "extern");
           return result;
         }
         result |= MethodFlags.PInvokeImpl;
         break;
       case Token.Unsafe:
         if (!this.allowUnsafeCode){
           this.allowUnsafeCode = true;
           this.HandleError(modifierContexts[i], Error.IllegalUnsafe);
         }
         this.inUnsafeCode = true;
         break;
       default:
         if (firstNonExtern == -1) firstNonExtern = i;
         else if (secondNonExtern == -1) secondNonExtern = i;
         break;
     }
   }
   destructor.IsUnsafe = this.inUnsafeCode;
   if (secondNonExtern >= 0 && Parser.ProtectionModifier[modifierTokens[secondNonExtern]])
     this.HandleError(modifierContexts[secondNonExtern], Error.ConflictingProtectionModifier);
   else if (firstNonExtern >= 0)
     this.HandleError(modifierContexts[firstNonExtern], Error.InvalidModifier, modifierContexts[firstNonExtern].SourceText);
   return result;
 }
예제 #7
0
 private void ParseMethod(TypeNode parentType, AttributeList attributes, TokenList modifierTokens,
   SourceContextList modifierContexts, object sctx, TypeNode type, TypeNode interfaceType, Identifier name, TokenSet followers){
   Method m = new Method(parentType, attributes, name, null, type, null);
   m.SourceContext = (SourceContext)sctx;
   m.ReturnTypeExpression = type;
   parentType.Members.Add(m);
   if (interfaceType != null){
     m.ImplementedTypeExpressions = m.ImplementedTypes = new TypeNodeList(interfaceType);
     m.Flags = MethodFlags.Private|MethodFlags.HideBySig|MethodFlags.NewSlot|MethodFlags.Final|MethodFlags.Virtual;
     for (int i = 0, n = modifierContexts == null ? 0 : modifierContexts.Length; i < n; i++){
       if (modifierTokens[i] == Token.Extern)
         m.Flags |= 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
     m.Flags = this.GetMethodFlags(modifierTokens, modifierContexts, parentType, m)|MethodFlags.HideBySig;
   if ((m.Flags & MethodFlags.Static) == 0)
     m.CallingConvention = CallingConventionFlags.HasThis;
   else if (parentType is Interface){
     this.HandleError(name.SourceContext, Error.InvalidModifier, "static");
     m.Flags &= ~MethodFlags.Static;
     m.Flags |= MethodFlags.Abstract;
   }
   m.Documentation = this.LastDocComment;
   if (this.currentToken == Token.LessThan)
     this.ParseTypeParameters(m, followers|Token.LeftParenthesis|Token.LeftBrace);
   m.Parameters = this.ParseParameters(Token.RightParenthesis, followers|Token.LeftBrace|Token.Semicolon|Token.Requires|Token.Modifies|Token.Ensures|Token.Where|Token.Throws);
   while (this.currentToken == Token.Where)
     this.ParseTypeParameterConstraint(m, followers|Token.LeftBrace|Token.Semicolon|Token.Requires|Token.Modifies|Token.Ensures|Token.Where|Token.Throws);
   m.HasCompilerGeneratedSignature = false;
   bool swallowedSemicolonAlready = false;
   bool abstractMethod = false;
   if (this.currentToken == Token.Semicolon) {
     // allow for "f(...); requires P; ensures Q;" for interface methods and abstract methods
     // I.e., a semi-colon after the parameter list. The "swallowedSemicolonAlready" flag
     // was an attempt to allow "f(...) requires P;", but for C#-compatibility mode where
     // the contracts are in C# comments, that forces the last semi to be on a separate line
     // and the C# formatter makes it look ugly.
     abstractMethod = true;
     swallowedSemicolonAlready = true;
     m.SourceContext.EndPos = this.scanner.endPos;
     this.GetNextToken();
   }
   this.ParseMethodContract(m, followers|Token.LeftBrace|Token.Semicolon, ref swallowedSemicolonAlready);
   if (!abstractMethod) {
     m.Body = this.ParseBody(m, sctx, followers, swallowedSemicolonAlready);
     if (m.Body != null)
       m.SourceContext.EndPos = m.Body.SourceContext.EndPos;
   } else if (!swallowedSemicolonAlready) {
     m.SourceContext.EndPos = this.scanner.endPos;
     this.SkipSemiColon(followers);
   }
 }
예제 #8
0
 private void ParseConst(TypeNode parentType, AttributeList attributes, TokenList modifierTokens, SourceContextList modifierContexts, SourceContext sctx, TokenSet followers){
   Debug.Assert(this.currentToken == Token.Const);
   this.GetNextToken();
   TokenSet followersOrCommaOrSemiColon = followers|Token.Comma|Token.Semicolon;
   TypeNode type = this.ParseTypeExpression(null, followersOrCommaOrSemiColon|Parser.IdentifierOrNonReservedKeyword|Token.Assign);
   Identifier name = this.scanner.GetIdentifier();
   Field f = new Field(parentType, attributes, FieldFlags.None, name, type, null);
   f.TypeExpression = type;
   f.SourceContext = sctx;
   FieldFlags flags = this.GetFieldFlags(modifierTokens, modifierContexts, f);
   if (f.IsVolatile){
     f.IsVolatile = false;
     for (int i = 0, n = modifierTokens.Length; i < n; i++){
       Token tok = modifierTokens[i];
       if (tok == Token.Volatile){
         this.HandleError(modifierContexts[i], Error.InvalidModifier, "volatile");
         break;
       }
     }
   }
   f.Documentation = this.LastDocComment;
   f.Flags = flags|FieldFlags.Static|FieldFlags.Literal|FieldFlags.HasDefault;
   if ((flags&FieldFlags.Static) != 0)
     this.HandleError(Error.StaticConstant, parentType.Name+"."+name);
   this.SkipIdentifierOrNonReservedKeyword();
   for(;;){
     if (this.currentToken == Token.Assign)
       this.GetNextToken();
     else if (this.currentToken == Token.LeftBrace && parentType is Interface){
       //might be a mistaken attempt to define a readonly property
       this.HandleError(Error.ConstValueRequired); //TODO: this is as per the C# compiler, but a better message would be nice.
       this.ParseProperty(parentType, attributes, modifierTokens, modifierContexts, sctx, type, null, name, followers);
       return;
     }else{
       this.SkipTo(Parser.UnaryStart|followersOrCommaOrSemiColon, Error.ConstValueRequired);
       if (this.currentToken == Token.Comma) goto carryOn;
       if (!Parser.UnaryStart[this.currentToken]){
         if (followers[this.currentToken]) return;
         break;
       }
     }
     f.Initializer = this.ParseExpression(followersOrCommaOrSemiColon);
     if (this.currentToken != Token.Comma) break;
   carryOn:
     this.GetNextToken();
     parentType.Members.Add(f);
     f = new Field(parentType, attributes, flags|FieldFlags.Static|FieldFlags.Literal|FieldFlags.HasDefault, this.scanner.GetIdentifier(), type, null);
     f.TypeExpression = type;
     this.SkipIdentifierOrNonReservedKeyword();
   }
   parentType.Members.Add(f);
   f.SourceContext.EndPos = this.scanner.endPos;
   this.SkipSemiColon(followers);
   this.SkipTo(followers);
 }
예제 #9
0
 private Field ParseField(TypeNode parentType, AttributeList attributes, TokenList modifierTokens,
   SourceContextList modifierContexts, object sctx, TypeNode type, Identifier name, TokenSet followers){
   Field f = new Field(parentType, attributes, FieldFlags.Public, name, type, null);
   f.TypeExpression = type;
   f.Flags = this.GetFieldFlags(modifierTokens, modifierContexts, f);
   f.SourceContext = (SourceContext)sctx;
   f.Documentation = this.LastDocComment;
   TokenSet modifiedFollowers = followers|Token.Comma|Token.Semicolon;
   for (;;){
     if (this.currentToken == Token.Assign){
       bool savedParsingStatement = this.parsingStatement;
       this.parsingStatement = true;
       this.GetNextToken();
       if (this.currentToken == Token.LeftBrace){
         f.Initializer = this.ParseArrayInitializer(type, modifiedFollowers);
       }else
         f.Initializer = this.ParseExpression(modifiedFollowers);
       if (this.currentToken != Token.EndOfFile) this.parsingStatement = savedParsingStatement;
     }
     f.SourceContext.EndPos = this.scanner.endPos;
     parentType.Members.Add(f);
     if (this.currentToken != Token.Comma) break;
     this.GetNextToken();
     name = this.scanner.GetIdentifier();
     f = new Field(parentType, attributes, f.Flags, name, type, null);
     f.TypeExpression = type;
     f.SourceContext = name.SourceContext;
     this.SkipIdentifierOrNonReservedKeyword();
   }
   this.SkipSemiColon(followers);
   return f;
 }
예제 #10
0
 private void ParseFieldOrMethodOrPropertyOrStaticInitializer(TypeNode t, TypeNode parentType, AttributeList attributes, TokenList modifierTokens,
   SourceContextList modifierContexts, object sctx, SourceContext idCtx, TokenSet followers){
   if (Parser.IsVoidType(t) && this.currentToken == Token.LeftParenthesis){
     this.ParseConstructor(parentType, attributes, modifierTokens, modifierContexts, sctx, idCtx, followers|Token.Semicolon);
     if (this.currentToken == Token.Semicolon) this.GetNextToken();
     this.SkipTo(followers);
     return;
   }
   bool badModifier = false;
 tryAgain:
   switch (this.currentToken){
     case Token.This:
       Identifier itemId = new Identifier("Item");
       itemId.SourceContext = this.scanner.CurrentSourceContext;
       this.ParseProperty(parentType, attributes, modifierTokens, modifierContexts, sctx, t, null, itemId, followers);
       return;
     case Token.Explicit:
     case Token.Implicit:
     case Token.Operator:
       this.ParseOperator(parentType, attributes, modifierTokens, modifierContexts, t, sctx, followers);
       return;
     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:
       if (this.scanner.TokenIsFirstAfterLineBreak) break;
       if (!badModifier){
         this.HandleError(Error.BadModifierLocation, this.scanner.GetTokenSource());
         badModifier = true;
       }
       this.GetNextToken();
       goto tryAgain;
     case Token.LeftParenthesis:
     case Token.LessThan:
       if (t is TypeExpression && ((TypeExpression)t).Expression is Identifier){
         this.HandleError(t.SourceContext, Error.MemberNeedsType);
         this.ParseMethod(parentType, attributes, modifierTokens, modifierContexts, sctx,
           this.TypeExpressionFor(Token.Void), null, (Identifier)((TypeExpression)t).Expression, followers);
         return;
       }
       break;
     default:
       if (!Parser.IdentifierOrNonReservedKeyword[this.currentToken]){
         if (followers[this.currentToken])
           this.HandleError(Error.ExpectedIdentifier);
         else
           this.SkipTo(followers);
         this.ParseField(parentType, attributes, modifierTokens, modifierContexts, sctx, t, Identifier.Empty, followers);
         return;
       }
       break;
   }
   TypeExpression interfaceType = null;
   Identifier id = this.scanner.GetIdentifier();
   if (badModifier) id.SourceContext.Document = null; //suppress any further errors involving this member
   this.SkipIdentifierOrNonReservedKeyword();
   if (this.currentToken == Token.DoubleColon){
     Identifier prefix = id;
     this.GetNextToken();
     id = this.scanner.GetIdentifier();
     id.Prefix = prefix;
     id.SourceContext.StartPos = prefix.SourceContext.StartPos;
     this.SkipIdentifierOrNonReservedKeyword();
   }
   if (this.currentToken == Token.Dot){
     this.GetNextToken();
     if (this.ExplicitInterfaceImplementationIsAllowable(parentType, id))
       interfaceType = new TypeExpression(id, id.SourceContext);
     if (this.currentToken == Token.This){
       id = new Identifier("Item");
       id.SourceContext = this.scanner.CurrentSourceContext;
     }else{
       id = this.scanner.GetIdentifier();
       this.SkipIdentifierOrNonReservedKeyword();
     }
     if (interfaceType == null) id.SourceContext.Document = null;
   }
 onceMore:
   switch(this.currentToken){
     case Token.This:
       if (interfaceType == null) goto default;
       goto case Token.LeftBrace;
     case Token.LeftBrace:
       this.ParseProperty(parentType, attributes, modifierTokens, modifierContexts, sctx, t, interfaceType, id, followers);
       return;
     case Token.LeftParenthesis:
       this.ParseMethod(parentType, attributes, modifierTokens, modifierContexts, sctx, t, interfaceType, id, followers);
       return;
     case Token.LessThan:
       if (modifierTokens == null || modifierTokens.Length == 0) {
         TypeExpression intfExpr = interfaceType;
         if (intfExpr == null) {
           if (parentType is Class || parentType is Struct)
             intfExpr = new TypeExpression(id, id.SourceContext);
           else
             goto case Token.LeftParenthesis;
         }
         int savedStartPos = this.scanner.startPos;
         ScannerState ss = this.scanner.state;
         int endPos, arity;
         TypeNodeList templateArguments = this.ParseTypeArguments(true, false, followers | Token.Dot | Token.LeftParenthesis | Token.LeftBrace, out endPos, out arity);
         if (templateArguments != null && this.currentToken == Token.Dot) {
           if (intfExpr != null && intfExpr.Expression != id) {
             SourceContext ctx = intfExpr.Expression.SourceContext;
             ctx.EndPos = id.SourceContext.EndPos;
             intfExpr.Expression = new QualifiedIdentifier(intfExpr.Expression, id, ctx);
           }
           intfExpr.TemplateArguments = templateArguments;
           intfExpr.SourceContext.EndPos = endPos;
           interfaceType = intfExpr;
           this.GetNextToken();
           if (this.currentToken == Token.This) {
             id = new Identifier("Item");
             id.SourceContext = this.scanner.CurrentSourceContext;
           } else {
             id = this.scanner.GetIdentifier();
             this.SkipIdentifierOrNonReservedKeyword();
           }
           goto onceMore;
         }
         this.scanner.state = ss;
         this.scanner.endPos = savedStartPos;
         this.currentToken = Token.None;
         this.GetNextToken();
         Debug.Assert(this.currentToken == Token.LessThan);
       }
       goto case Token.LeftParenthesis;
     case Token.Dot:
       if (interfaceType != null){
         this.GetNextToken();
         SourceContext ctx = interfaceType.Expression.SourceContext;
         ctx.EndPos = id.SourceContext.EndPos;
         interfaceType.SourceContext.EndPos = id.SourceContext.EndPos;
         interfaceType.Expression = new QualifiedIdentifier(interfaceType.Expression, id, ctx);
         if (this.currentToken == Token.This) {
           id = new Identifier("Item");
           id.SourceContext = this.scanner.CurrentSourceContext;
         } else {
           id = this.scanner.GetIdentifier();
           this.SkipIdentifierOrNonReservedKeyword();
         }
         goto onceMore;
       }
       goto default;
     default:
       if (interfaceType != null)
         this.ParseMethod(parentType, attributes, modifierTokens, modifierContexts, sctx, t, interfaceType, id, followers);
       else
         this.ParseField(parentType, attributes, modifierTokens, modifierContexts, sctx, t, id, followers);
       return;
   }
 }
예제 #11
0
    /// <summary>
    /// Parse a modelfield. Requires that the model keyword has been swallowed already.
    /// Adds a new ModelfieldContract to parentType.Contract and, if the modelfield is not an override, adds a Member to parentType that represents the modelfield.
    /// </summary>
    private void ParseModelField(TypeNode parentType, AttributeList attributes, TokenList modifierTokens,
      SourceContextList modifierContexts, object sctx, TokenSet followers)
    {
      //A model field has the shape [new | override | sealed] model T name {ConstraintsAndWitness}.
      //override is not allowed if parentype is Interface.
      //model T name; is accepted as a shorthand for model T name {witness 0;}.
      #region parse type T
      //Expecting type T as currentToken.
      if (this.currentToken == Token.EndOfFile) {
        this.HandleError(Error.ExpectedExpression); return;
      }
      TypeNode type = this.ParseTypeExpression(parentType.ConstructorName, followers | Parser.IdentifierOrNonReservedKeyword);
      #endregion
      #region parse identifier name
      //Expecting identifier f
      if (!Parser.IdentifierOrNonReservedKeyword[this.currentToken]) {
        this.HandleError(Error.ExpectedIdentifier);
        if (this.currentToken != Token.EndOfFile)
          this.SkipTo(followers);
        return;
      }
      Identifier name = this.scanner.GetIdentifier();
      #endregion

      ModelfieldContract mfC = new ModelfieldContract(parentType, attributes, type, name, name.SourceContext);

      #region handle modifiers
      bool isNew = false;
      for (int i = 0, n = modifierTokens.Length; i < n; i++) {
        switch (modifierTokens[i]) {
          case Token.New:
            if (isNew || mfC.IsOverride || parentType is Interface)
              this.HandleError(modifierContexts[i], Error.InvalidModifier, modifierContexts[i].SourceText);
            else {
              isNew = true;
              (mfC.Modelfield as Field).HidesBaseClassMember = true;
            }
            break;
          case Token.Override:
            if (isNew || mfC.IsOverride || parentType is Interface)
              this.HandleError(modifierContexts[i], Error.InvalidModifier, modifierContexts[i].SourceText);
            else {
              mfC.IsOverride = true;
            }
            break;
          case Token.Sealed:
            if (mfC.IsSealed)
              this.HandleError(modifierContexts[i], Error.DuplicateModifier, modifierContexts[i].SourceText);
            else
              mfC.IsSealed = true;
            break;
          default:
            this.HandleError(modifierContexts[i], Error.InvalidModifier, modifierContexts[i].SourceText);
            break;
        }
      }
      #endregion

      this.GetNextToken(); //now expect either a semicolon, or {ConstraintsAndWitness}
      if (this.currentToken == Token.Semicolon) {
        this.GetNextToken();
      } else {
        this.Skip(Token.LeftBrace);
        #region Parse zero or more satisfies clauses (satisfies true on zero) and zero or one witness clauses
        while (this.currentToken == Token.Witness || this.currentToken == Token.Satisfies) {
          if (this.currentToken == Token.Witness) {
            if (!mfC.HasExplicitWitness) { //did not parse a witness yet
              this.GetNextToken();
              mfC.Witness = this.ParseExpression(followers | Token.Semicolon);
              mfC.HasExplicitWitness = true;
              this.Skip(Token.Semicolon);
            } else {
              this.HandleError(Error.UnexpectedToken, this.scanner.GetTokenSource()); //there should be at most one witness
              this.GetNextToken(); break;
            }
          } else if (this.currentToken == Token.Satisfies) {
            this.GetNextToken();
            Expression sat = this.ParseExpression(followers | Token.Semicolon);
            if (sat != null && !(parentType is Interface))
              mfC.SatisfiesList.Add(sat);
            else if (parentType is Interface)
              this.HandleError(Error.SatisfiesInInterface, this.scanner.GetTokenSource());
            this.Skip(Token.Semicolon);
          }
        }
        #endregion
        this.Skip(Token.RightBrace);
      }
      if (parentType.Contract == null)
        parentType.Contract = new TypeContract(parentType);
      parentType.Contract.ModelfieldContracts.Add(mfC);
      if (!mfC.IsOverride)
        parentType.Members.Add(mfC.Modelfield);
      //this.SkipSemiColon(followers); a modelfield is not terminated by a ;
    }
예제 #12
0
 private void ParseFieldOrMethodOrPropertyOrStaticInitializer(TypeNode parentType, AttributeList attributes, TokenList modifierTokens,
   SourceContextList modifierContexts, object sctx, TokenSet followers){
   SourceContext idCtx = this.scanner.CurrentSourceContext;
   TypeNode t = this.ParseTypeExpression(parentType.ConstructorName, followers|Parser.IdentifierOrNonReservedKeyword|Token.Explicit|Token.Implicit);
   this.ParseFieldOrMethodOrPropertyOrStaticInitializer(t, parentType, attributes, modifierTokens, modifierContexts, sctx, idCtx, followers);
 }
예제 #13
0
 private TypeFlags NestedTypeFlags(TokenList modifierTokens, SourceContextList modifierContexts, Member ntype, bool isPartial){
   TypeFlags result = TypeFlags.None;
   for(int i = 0, n = modifierTokens.Length; i < n; i++){
     switch(modifierTokens[i]){
       case Token.New:
         if (ntype.HidesBaseClassMember)
           this.HandleError(modifierContexts[i], Error.DuplicateModifier, "new");
         ntype.HidesBaseClassMember = true;
         break;
       case Token.Public:
         if ((result & TypeFlags.VisibilityMask) != 0){
           if ((result & TypeFlags.VisibilityMask) == TypeFlags.NestedPublic)
             this.HandleError(modifierContexts[i], Error.DuplicateModifier, "public");
           else
             this.HandleError(modifierContexts[i],Error.ConflictingProtectionModifier);
         }
         result |= TypeFlags.NestedPublic;
         break;
       case Token.Protected:
         if (ntype != null && ntype.DeclaringType is Struct){
           this.HandleError(modifierContexts[i], Error.InvalidModifier, "protected");
           break;
         }
         if ((result & TypeFlags.VisibilityMask) != 0){
           if ((result & TypeFlags.VisibilityMask) == TypeFlags.NestedFamily || (result & TypeFlags.VisibilityMask) == TypeFlags.NestedFamORAssem)
             this.HandleError(modifierContexts[i], Error.DuplicateModifier, "protected");
           else if ((result & TypeFlags.NestedAssembly) != 0){
             result &= ~TypeFlags.NestedAssembly;
             result |= TypeFlags.NestedFamORAssem;
             break;
           }else
             this.HandleError(modifierContexts[i], Error.ConflictingProtectionModifier);
         }
         result |= TypeFlags.NestedFamily;
         break;
       case Token.Internal:
         if ((result & TypeFlags.VisibilityMask) != 0){
           if ((result & TypeFlags.VisibilityMask) == TypeFlags.NestedAssembly || (result & TypeFlags.VisibilityMask) == TypeFlags.NestedFamORAssem)
             this.HandleError(Error.DuplicateModifier, "internal");
           else if ((result & TypeFlags.NestedFamily) != 0){
             result &= ~TypeFlags.NestedFamily;
             result |= TypeFlags.NestedFamORAssem;
             break;
           }else
             this.HandleError(modifierContexts[i], Error.ConflictingProtectionModifier);
         }
         result |= TypeFlags.NestedAssembly;
         break;
       case Token.Private:
         if ((result & TypeFlags.VisibilityMask) != 0){
           if ((result & TypeFlags.VisibilityMask) == TypeFlags.NestedPrivate)
             this.HandleError(modifierContexts[i], Error.DuplicateModifier, "private");
           else
             this.HandleError(modifierContexts[i], Error.ConflictingProtectionModifier);
         }
         result |= TypeFlags.NestedPrivate;
         break;
       case Token.Abstract:
         if (!(ntype is Class)){
           this.HandleError(Error.InvalidModifier, "abstract");
           break;
         }
         if ((result & TypeFlags.Abstract) != 0)
           this.HandleError(modifierContexts[i], Error.DuplicateModifier, "abstract");
         result |= TypeFlags.Abstract;
         break;
       case Token.Sealed:
         if (!(ntype is Class)){
           this.HandleError(Error.InvalidModifier, "sealed");
           break;
         }
         if ((result & TypeFlags.Sealed) != 0)
           this.HandleError(modifierContexts[i], Error.DuplicateModifier, "sealed");
         result |= TypeFlags.Sealed;
         break;
       case Token.Static:
         if (!(ntype is Class)){
           this.HandleError(Error.InvalidModifier, "static");
           break;
         }
         if ((result & TypeFlags.Sealed) != 0)
           this.HandleError(modifierContexts[i], Error.DuplicateModifier, "sealed");
         if ((result & TypeFlags.Abstract) != 0)
           this.HandleError(modifierContexts[i], Error.DuplicateModifier, "abstract");
         result |= TypeFlags.Abstract|TypeFlags.Sealed|TypeFlags.SpecialName;
         break;
       case Token.Readonly:
         this.HandleError(Error.InvalidModifier, "readonly");
         break;
       case Token.Volatile:
         this.HandleError(Error.InvalidModifier, "volatile");
         break;
       case Token.Virtual:
         this.HandleError(Error.InvalidModifier, "virtual");
         break;
       case Token.Override:
         this.HandleError(Error.InvalidModifier, "override");
         break;
       case Token.Extern:
         this.HandleError(Error.InvalidModifier, "extern");
         break;
       case Token.Unsafe:
         if (!this.allowUnsafeCode){
           this.allowUnsafeCode = true;
           this.HandleError(modifierContexts[i], Error.IllegalUnsafe);
         }
         if (ntype is EnumNode){
           this.HandleError(Error.InvalidModifier, "unsafe");
           break;
         }
         this.inUnsafeCode = true;
         break;
       default:
         Debug.Assert(false);
         break;
     }
   }
   ntype.IsUnsafe = this.inUnsafeCode;
   if ((result & TypeFlags.VisibilityMask) == 0){
     result |= TypeFlags.NestedPrivate;
     if (isPartial) result |= TypeFlags.RTSpecialName;
   }
   return result;
 }
예제 #14
0
 private TypeFlags NestedTypeFlags(TokenList modifierTokens, SourceContextList modifierContexts, Member ntype){
   return this.NestedTypeFlags(modifierTokens, modifierContexts, ntype, false);
 }
예제 #15
0
 private MethodFlags GetOperatorFlags(TokenList modifierTokens, SourceContextList modifierContexts, SourceContext ctx){
   MethodFlags result = (MethodFlags)0;
   for (int i = 0, n = modifierTokens.Length; i < n; i++){
     switch(modifierTokens[i]){
       case Token.Public:
         if ((result & MethodFlags.MethodAccessMask) == MethodFlags.Public)
           this.HandleError(modifierContexts[i], Error.DuplicateModifier, "public");
         result |= MethodFlags.Public;
         break;
       case Token.Static:
         if ((result & MethodFlags.Static) != 0)
           this.HandleError(modifierContexts[i], Error.DuplicateModifier, "static");
         result |= MethodFlags.Static;
         break;
       case Token.Extern:
         if ((result & MethodFlags.PInvokeImpl) != 0)
           this.HandleError(modifierContexts[i], Error.DuplicateModifier, "extern");
         result |= MethodFlags.PInvokeImpl;
         break;
       case Token.Unsafe:
         if (!this.allowUnsafeCode){
           this.allowUnsafeCode = true;
           this.HandleError(modifierContexts[i], Error.IllegalUnsafe);
         }
         this.inUnsafeCode = true;
         break;
       default:
         //TODO: search for duplicate, preferentially complain about that for backwards compat with C#
         this.HandleError(modifierContexts[i], Error.InvalidModifier, modifierContexts[i].SourceText);
         break;
     }
   }
   if (result != (MethodFlags.Public|MethodFlags.Static) &&
       result != (MethodFlags.Public|MethodFlags.Static|MethodFlags.PInvokeImpl)){
     this.HandleError(ctx, Error.OperatorsMustBeStatic, ctx.SourceText);
     result |= MethodFlags.Public|MethodFlags.Static;
   }
   return result|MethodFlags.SpecialName|MethodFlags.HideBySig;
 }
예제 #16
0
 private FieldFlags GetFieldFlags(TokenList modifierTokens, SourceContextList modifierContexts, Field f){
   FieldFlags result = (FieldFlags)0;
   if (modifierTokens == null) return result;
   for (int i = 0, n = modifierTokens.Length; i < n; i++){
     switch(modifierTokens[i]){
       case Token.New:
         if (f.HidesBaseClassMember)
           this.HandleError(modifierContexts[i], Error.DuplicateModifier, "new");
         f.HidesBaseClassMember = true;
         break;
       case Token.Public:
         FieldFlags access = result & FieldFlags.FieldAccessMask;
         if (access == FieldFlags.Public)
           this.HandleError(modifierContexts[i], Error.DuplicateModifier, "public");
         else if (access != 0)
           this.HandleError(modifierContexts[i], Error.ConflictingProtectionModifier);
         result |= FieldFlags.Public;
         break;
       case Token.Protected:
         access = result & FieldFlags.FieldAccessMask;
         if (access == FieldFlags.Family || access == FieldFlags.FamORAssem)
           this.HandleError(modifierContexts[i], Error.DuplicateModifier, "protected");
         else if (access == FieldFlags.Assembly){
           result &= ~FieldFlags.Assembly;
           result |= FieldFlags.FamORAssem;
           break;
         }else if (access != 0)
           this.HandleError(modifierContexts[i], Error.ConflictingProtectionModifier);
         result |= FieldFlags.Family;
         break;
       case Token.Internal:
         access = result & FieldFlags.FieldAccessMask;
         if (access == FieldFlags.Assembly || access == FieldFlags.FamORAssem)
           this.HandleError(modifierContexts[i], Error.DuplicateModifier, "internal");
         else if (access == FieldFlags.Family){
           result &= ~FieldFlags.Family;
           result |= FieldFlags.FamORAssem;
           break;
         }else if (access != 0)
           this.HandleError(modifierContexts[i], Error.ConflictingProtectionModifier);
         result |= FieldFlags.Assembly;
         break;
       case Token.Private:
         access = result & FieldFlags.FieldAccessMask;
         if (access == FieldFlags.Private)
           this.HandleError(modifierContexts[i], Error.DuplicateModifier, "private");
         else if (access != 0)
           this.HandleError(modifierContexts[i], Error.ConflictingProtectionModifier);
         result |= FieldFlags.Private;
         break;
       case Token.Abstract:
         if (modifierContexts[i].Document != null)
           this.HandleError(modifierContexts[i], Error.InvalidModifier, "abstract");
         break;
       case Token.Sealed:
         this.HandleError(modifierContexts[i], Error.InvalidModifier, "sealed");
         break;
       case Token.Static:
         if ((result & FieldFlags.Static) != 0)
           this.HandleError(modifierContexts[i], Error.DuplicateModifier, "static");
         result |= FieldFlags.Static;
         break;
       case Token.Readonly:
         if ((result & FieldFlags.InitOnly) != 0)
           this.HandleError(modifierContexts[i], Error.DuplicateModifier, "readonly");
         result |= FieldFlags.InitOnly;
         break;
       case Token.Volatile:
         if (f.IsVolatile)
           this.HandleError(modifierContexts[i], Error.DuplicateModifier, "volatile");
         f.IsVolatile = true;
         break;
       case Token.Virtual:
         this.HandleError(modifierContexts[i], Error.InvalidModifier, "virtual");
         break;
       case Token.Override:
         this.HandleError(modifierContexts[i], Error.InvalidModifier, "override");
         break;
       case Token.Extern:
         this.HandleError(modifierContexts[i], Error.InvalidModifier, "extern");
         break;
       case Token.Unsafe:
         if (!this.allowUnsafeCode){
           this.allowUnsafeCode = true;
           this.HandleError(modifierContexts[i], Error.IllegalUnsafe);
         }
         this.inUnsafeCode = true;
         break;
       default:
         Debug.Assert(f.DeclaringType is Interface);
         this.HandleError(f.Name.SourceContext, Error.InvalidModifier, modifierContexts[i].SourceText);
         break;
     }
   }
   f.IsUnsafe = this.inUnsafeCode;
   if ((result & FieldFlags.FieldAccessMask) == 0)
     result |= FieldFlags.Private;
   return result;
 }
예제 #17
0
 private void ParseDestructor(TypeNode parentType, AttributeList attributes, TokenList modifierTokens,
   SourceContextList modifierContexts, object sctx, TokenSet followers){
   Method meth = new Method(parentType, attributes, new Identifier("Finalize"), null, this.TypeExpressionFor(Token.Void), null);
   meth.OverridesBaseClassMember = !this.TypeIsSystemObject(parentType);
   meth.Documentation = this.LastDocComment;
   meth.Flags = this.GetDestructorFlags(modifierTokens, modifierContexts, meth);
   meth.CallingConvention = CallingConventionFlags.HasThis;
   Debug.Assert(this.currentToken == Token.BitwiseNot);
   this.GetNextToken();
   if (!(parentType is Class))
     this.HandleError(Error.OnlyClassesCanContainDestructors);
   else
     parentType.Members.Add(meth);
   Identifier id = this.scanner.GetIdentifier();
   meth.Name.SourceContext = id.SourceContext;
   this.SkipIdentifierOrNonReservedKeyword();
   if (id.UniqueIdKey != parentType.Name.UniqueIdKey)
     this.HandleError(Error.WrongNameForDestructor);
   ParameterList pars = this.ParseParameters(Token.RightParenthesis, followers|Token.LeftBrace);
   if (pars != null && pars.Count > 0 && pars[0] != null)
     this.HandleError(pars[0].SourceContext, Error.ExpectedRightParenthesis);
   Block b = this.ParseBody(meth, sctx, followers);
   if (b != null && !this.TypeIsSystemObject(parentType)) {
     StatementList stats = new StatementList(1);
     stats.Add(new ExpressionStatement(new MethodCall(new QualifiedIdentifier(new Base(), StandardIds.Finalize), null)));
     Try t = new Try(b, null, null, null, new Finally(new Block(stats, this.insideCheckedBlock, this.insideUncheckedBlock, this.inUnsafeCode)));
     stats = new StatementList(1);
     stats.Add(t);
     meth.Body = new Block(stats, this.insideCheckedBlock, this.insideUncheckedBlock, this.inUnsafeCode);
   } else
     meth.Body = b;
 }
예제 #18
0
 private TypeNode ParseDelegateDeclaration(Namespace ns, TypeNode parentType, AttributeList attributes, TokenList modifierTokens,
   SourceContextList modifierContexts, SourceContext sctx, TokenSet followers){
   return this.ParseDelegateDeclaration(ns, parentType, attributes, modifierTokens, modifierContexts, TypeFlags.None, sctx, followers);
 }
예제 #19
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;
     }
   }
 }
예제 #20
0
 private TypeNode ParseDelegateDeclaration(Namespace ns, TypeNode parentType, AttributeList attributes, TokenList modifierTokens,
   SourceContextList modifierContexts, TypeFlags flags, SourceContext sctx, TokenSet followers){
   DelegateNode d = new DelegateNode();
   d.Attributes = attributes;
   if (parentType == null)
     d.DeclaringNamespace = ns;
   else{
     d.DeclaringType = parentType;
     d.IsGeneric = parentType.IsGeneric;
   }
   d.DeclaringModule = this.module;
   d.SourceContext = sctx;
   d.Documentation = this.LastDocComment;
   Debug.Assert(this.currentToken == Token.Delegate);
   this.GetNextToken();
   if (this.currentToken == Token.Void){
     d.ReturnType = this.TypeExpressionFor(Token.Void);
     this.GetNextToken();
   }else
     d.ReturnType = d.ReturnTypeExpression =
       this.ParseTypeOrFunctionTypeExpression(followers|Parser.IdentifierOrNonReservedKeyword|Token.Semicolon, false, false);
   if ((this.currentToken == Token.LeftParenthesis && parentType != null) ||
     (ns == null && parentType == null && attributes == null && modifierTokens == null && flags == TypeFlags.None))
     d.Name = Identifier.Empty;
   else{
     d.Name = this.scanner.GetIdentifier();
     this.SkipIdentifierOrNonReservedKeyword();
     if (modifierTokens != null)
       d.Flags |= this.NestedTypeFlags(modifierTokens, modifierContexts, d)|TypeFlags.Sealed;
     else{
       if ((flags & (TypeFlags.Abstract|TypeFlags.Sealed|TypeFlags.SpecialName)) != 0){
         this.HandleError(d.Name.SourceContext, Error.InvalidModifier, "static");
         flags &= ~(TypeFlags.Abstract|TypeFlags.Sealed|TypeFlags.SpecialName);
       }
       d.IsUnsafe = this.inUnsafeCode;
       d.Flags |= flags|TypeFlags.Sealed;
     }
     if (this.currentToken == Token.LessThan){
       this.ParseTypeParameters(d, followers|Token.LeftParenthesis|Token.RightParenthesis|Token.Semicolon|Token.Where);
       if (Cci.TargetPlatform.GenericTypeNamesMangleChar != 0) {
         int numPars = d.TemplateParameters == null ? 0 : d.TemplateParameters.Count;
         if (numPars > 0)
           d.Name = new Identifier(d.Name.ToString()+Cci.TargetPlatform.GenericTypeNamesMangleChar+numPars.ToString(), d.Name.SourceContext);
       }
     }
     if (parentType != null){
       d.Namespace = Identifier.Empty;
       parentType.Members.Add(d);
     }else{
       d.Namespace = ns.FullNameId;
       ns.Types.Add(d);
       this.AddTypeToModule(d);
     }
   }
   d.Parameters = this.ParseParameters(Token.RightParenthesis, followers|Token.Semicolon|Token.Where, true, false);
   while (this.currentToken == Token.Where)
     this.ParseTypeParameterConstraint(d, followers|Token.Semicolon|Token.Where);
   d.SourceContext.EndPos = this.scanner.endPos;
   if (d.Name != Identifier.Empty){
     this.SkipSemiColon(followers|Parser.TypeMemberStart);
     if (!followers[this.currentToken]) this.SkipTo(followers, Error.NamespaceUnexpected);
     return d;
   }else{
     this.SkipTo(followers|Parser.IdentifierOrNonReservedKeyword);
     return new FunctionTypeExpression(d.ReturnType, d.Parameters);
   }
 }
예제 #21
0
 private MethodFlags GetMethodFlags(TokenList modifierTokens, SourceContextList modifierContexts, TypeNode type, Member member){
   MethodFlags result = MethodFlags.HideBySig;
   if (type is Interface){
     result |= MethodFlags.Public|MethodFlags.Abstract|MethodFlags.NewSlot|MethodFlags.Virtual;
     for(int i = 0, n = modifierTokens.Length; i < n; i++){
       MethodFlags access = result & MethodFlags.MethodAccessMask;
       switch(modifierTokens[i]){
         case Token.New:
           for (int j = 0; j < i; j++){
             switch(modifierTokens[j]){
               case Token.New:
                 this.HandleError(modifierContexts[i], Error.DuplicateModifier, "new");
                 break;
             }
           }
           member.HidesBaseClassMember = true;
           i += 2;
           break;
         case Token.Static:
           if (n == 3) return MethodFlags.Static;
           goto default;
         case Token.Unsafe:
           if (!this.allowUnsafeCode){
             this.allowUnsafeCode = true;
             this.HandleError(modifierContexts[i], Error.IllegalUnsafe);
           }
           this.inUnsafeCode = true;
           break;
         default:
           this.HandleError(modifierContexts[i], Error.InvalidModifier, modifierContexts[i].SourceText);
           break;
       }
     }
     return result;
   }
   for(int i = 0, n = modifierTokens.Length; i < n; i++){
     MethodFlags access = result & MethodFlags.MethodAccessMask;
     switch(modifierTokens[i]){
       case Token.Public:
         if (access != 0){
           result &= ~MethodFlags.MethodAccessMask;
           if (access == MethodFlags.Public)
             this.HandleError(modifierContexts[i], Error.DuplicateModifier, "public");
           else
             this.HandleError(modifierContexts[i], Error.ConflictingProtectionModifier);
         }
         result |= MethodFlags.Public;
         break;
       case Token.Protected:
         if (access != 0){
           result &= ~MethodFlags.MethodAccessMask;
           if (access == MethodFlags.Family || access == MethodFlags.FamORAssem)
             this.HandleError(modifierContexts[i], Error.DuplicateModifier, "protected");
           else if (access == MethodFlags.Assembly){
             result |= MethodFlags.FamORAssem;
             break;
           }else
             this.HandleError(modifierContexts[i], Error.ConflictingProtectionModifier);
         }
         result |= MethodFlags.Family;
         break;
       case Token.Internal:
         if (access != 0){
           result &= ~MethodFlags.MethodAccessMask;
           if (access == MethodFlags.Assembly || access == MethodFlags.FamORAssem)
             this.HandleError(Error.DuplicateModifier, "internal");
           else if (access == MethodFlags.Family){
             result |= MethodFlags.FamORAssem;
             break;
           }else
             this.HandleError(modifierContexts[i], Error.ConflictingProtectionModifier);
         }
         result |= MethodFlags.Assembly;
         break;
       case Token.Private:
         if (access != 0){
           result &= ~MethodFlags.MethodAccessMask;
           if (access == MethodFlags.Private)
             this.HandleError(modifierContexts[i], Error.DuplicateModifier, "private");
           else
             this.HandleError(modifierContexts[i], Error.ConflictingProtectionModifier);
         }
         if ((result & MethodFlags.Virtual) != 0){
           string offendingMember = type.FullName;
           if (member != null)
             offendingMember = offendingMember + "." + member.Name;
           else
             offendingMember = offendingMember + "." + type.Name;
           this.HandleError(modifierContexts[i], Error.VirtualPrivate, offendingMember);
           break;
         }
         result |= MethodFlags.Private;
         break;
       case Token.Sealed:
         if ((result & MethodFlags.Final) != 0){
           this.HandleError(modifierContexts[i], Error.DuplicateModifier, "sealed");
           break;
         }
         for (int j = 0; j < n; j++){
           switch(modifierTokens[j]){
             case Token.Override:
               result |= MethodFlags.Final;
               break;
           }
         }
         if ((result & MethodFlags.Final) == 0){
           if (member != null)
             this.HandleError(modifierContexts[i], Error.SealedNonOverride, type.FullName+"."+member.Name);
         }
         break;
       case Token.Static:
         if ((result & MethodFlags.Static) != 0)
           this.HandleError(modifierContexts[i], Error.DuplicateModifier, "static");
         if (member is Property && member.Name.UniqueIdKey == StandardIds.Item.UniqueIdKey)
           this.HandleError(modifierContexts[i], Error.InvalidModifier, "static");
         result |= MethodFlags.Static;
         break;
       case Token.Readonly:
         this.HandleError(Error.InvalidModifier, "readonly");
         break;
       case Token.Volatile:
         this.HandleError(Error.InvalidModifier, "volatile");
         break;
       case Token.New:
         for (int j = 0; j < i; j++){
           switch(modifierTokens[j]){
             case Token.New:
               this.HandleError(modifierContexts[i], Error.DuplicateModifier, "new");
               break;
             case Token.Override:
               string offendingMember = type.FullName;
               if (member != null)
                 offendingMember = offendingMember + "." + member.Name;
               else
                 offendingMember = offendingMember + "." + type.Name;
               if (member is Property)
                 this.HandleError(modifierContexts[i], Error.CannotMarkOverridePropertyNewOrVitual, offendingMember);
               else if (member is Method)
                 this.HandleError(modifierContexts[i], Error.CannotMarkOverrideMethodNewOrVirtual, offendingMember);
               break;
           }
         }
         member.HidesBaseClassMember = true;
         break;
       case Token.Abstract:
         if (type is Struct){
           this.HandleError(modifierContexts[i], Error.InvalidModifier, modifierContexts[i].SourceText);
           break;
         }
         for (int j = 0; j < i; j++){
           switch(modifierTokens[j]){
             case Token.Abstract:
               this.HandleError(modifierContexts[i], Error.DuplicateModifier, "abstract");
               break;
             case Token.Virtual:
               string offendingMember = type.FullName;
               if (member != null)
                 offendingMember = offendingMember + "." + member.Name;
               else
                 offendingMember = offendingMember + "." + type.Name;
               if (member is Property)
                 this.HandleError(modifierContexts[j], Error.CannotMarkAbstractPropertyVirtual, offendingMember);
               else
                 this.HandleError(modifierContexts[j], Error.AbstractNotVirtual, offendingMember);
               break;
             case Token.Private:
               offendingMember = type.FullName;
               if (member != null)
                 offendingMember = offendingMember + "." + member.Name;
               else
                 offendingMember = offendingMember + "." + type.Name;
               this.HandleError(modifierContexts[j], Error.VirtualPrivate, offendingMember);
               break;
           }
         }
         result |= MethodFlags.Abstract | MethodFlags.Virtual | MethodFlags.CheckAccessOnOverride;
         if (!member.OverridesBaseClassMember) { result |= MethodFlags.NewSlot; }
         break;
       case Token.Virtual:
         if (type is Struct){
           this.HandleError(modifierContexts[i], Error.InvalidModifier, modifierContexts[i].SourceText);
           break;
         }
         if (type.IsSealed){
           this.HandleError(modifierContexts[i], Error.NewVirtualInSealed, modifierContexts[i].SourceText);
           break;
         }
         for (int j = 0; j < i; j++){
           switch(modifierTokens[j]){
             case Token.Virtual:
               this.HandleError(modifierContexts[i], Error.DuplicateModifier, "virtual");
               break;
             case Token.Abstract:
               string offendingMember = type.FullName;
               if (member != null)
                 offendingMember = offendingMember + "." + member.Name;
               else
                 offendingMember = offendingMember + "." + type.Name;
               if (member is Property)
                 this.HandleError(modifierContexts[i], Error.CannotMarkAbstractPropertyVirtual, offendingMember);
               else
                 this.HandleError(modifierContexts[i], Error.AbstractNotVirtual, offendingMember);
               break;
             case Token.Override:
               offendingMember = type.FullName;
               if (member != null)
                 offendingMember = offendingMember + "." + member.Name;
               else
                 offendingMember = offendingMember + "." + type.Name;
               this.HandleError(modifierContexts[i], Error.CannotMarkOverrideMethodNewOrVirtual, offendingMember);
               break;
             case Token.Private:
               offendingMember = type.FullName;
               if (member != null)
                 offendingMember = offendingMember + "." + member.Name;
               else
                 offendingMember = offendingMember + "." + type.Name;
               this.HandleError(modifierContexts[j], Error.VirtualPrivate, offendingMember);
               break;
           }
         }
         result |= MethodFlags.Virtual|MethodFlags.NewSlot|MethodFlags.CheckAccessOnOverride;
         break;
       case Token.Override:
         for (int j = 0; j < i; j++){
           switch(modifierTokens[j]){
             case Token.Override:
               this.HandleError(modifierContexts[i], Error.DuplicateModifier, "override");
               break;
             case Token.New:
             case Token.Virtual:
               string offendingMember = type.FullName;
               if (member != null)
                 offendingMember = offendingMember + "." + member.Name;
               else
                 offendingMember = offendingMember + "." + type.Name;
               if (member is Property)
                 this.HandleError(modifierContexts[j], Error.CannotMarkOverrideMethodNewOrVirtual, offendingMember);
               else
                 this.HandleError(modifierContexts[j], Error.CannotMarkOverrideMethodNewOrVirtual, offendingMember);
               break;
             case Token.Private:
               offendingMember = type.FullName;
               if (member != null)
                 offendingMember = offendingMember + "." + member.Name;
               else
                 offendingMember = offendingMember + "." + type.Name;
               this.HandleError(modifierContexts[j], Error.VirtualPrivate, offendingMember);
               break;
           }
         }
         result &= ~(MethodFlags.VtableLayoutMask);
         result |= MethodFlags.Virtual|MethodFlags.ReuseSlot;
         result &= ~(MethodFlags.NewSlot);
         member.OverridesBaseClassMember = true;
         break;
       case Token.Extern:
         if ((result & MethodFlags.PInvokeImpl) != 0)
           this.HandleError(modifierContexts[i], Error.DuplicateModifier, "extern");
         result |= MethodFlags.PInvokeImpl;
         break;
       case Token.Unsafe:
         if (!this.allowUnsafeCode){
           this.allowUnsafeCode = true;
           this.HandleError(modifierContexts[i], Error.IllegalUnsafe);
         }
         this.inUnsafeCode = true;
         break;
       default:
         Debug.Assert(false);
         this.HandleError(member.Name.SourceContext, Error.InvalidModifier, modifierContexts[i].SourceText);
         break;
     }
   }
   if ((result & MethodFlags.MethodAccessMask) == 0){
     if ((result & MethodFlags.Virtual) != 0){
       for (int i = 0, n = modifierTokens.Length; i < n; i++){
         switch (modifierTokens[i]){
           case Token.Abstract:
           case Token.Virtual:
             string offendingMember = type.FullName;
             if (member != null)
               offendingMember = offendingMember + "." + member.Name;
             else
               offendingMember = offendingMember + "." + type.Name;
             this.HandleError(modifierContexts[i], Error.VirtualPrivate, offendingMember);
             return result | MethodFlags.Private;
         }
       }
     }
     result |= MethodFlags.Private;
   }
   member.IsUnsafe = this.inUnsafeCode;
   return result;
 }
예제 #22
0
 private void ParseEnumDeclaration(Namespace ns, TypeNode parentType, AttributeList attributes, TokenList modifierTokens,
   SourceContextList modifierContexts, TypeFlags flags, SourceContext sctx, TokenSet followers){
   EnumNode e = new EnumNode();
   e.Attributes = attributes;
   if (parentType == null)
     e.DeclaringNamespace = ns;
   else{
     e.DeclaringType = parentType;
     e.IsGeneric = parentType.IsGeneric;
   }
   if (modifierTokens != null)
     e.Flags |= this.NestedTypeFlags(modifierTokens, modifierContexts, e)|TypeFlags.Sealed;
   else{
     if ((flags & TypeFlags.Abstract) != 0){
       if ((flags & TypeFlags.Sealed) != 0 && (flags & TypeFlags.SpecialName) != 0){
         this.HandleError(Error.InvalidModifier, "static");
         flags &= ~(TypeFlags.Abstract|TypeFlags.Sealed|TypeFlags.SpecialName);
       }else{
         this.HandleError(Error.InvalidModifier, "abstract");
         flags &= ~TypeFlags.Abstract;
       }
     }else if ((flags & TypeFlags.Sealed) != 0){
       this.HandleError(Error.InvalidModifier, "sealed");
       flags &= ~TypeFlags.Sealed;
     }
     e.Flags |= flags|TypeFlags.Sealed;
     e.IsUnsafe = this.inUnsafeCode;
   }
   e.SourceContext = sctx;
   e.DeclaringModule = this.module;
   Debug.Assert(this.currentToken == Token.Enum);
   this.GetNextToken();
   e.Name = this.scanner.GetIdentifier();
   this.SkipIdentifierOrNonReservedKeyword();
   if (parentType != null){
     e.Namespace = Identifier.Empty;
     parentType.Members.Add(e);
   }else{
     e.Namespace = ns.FullNameId;
     ns.Types.Add(e);
     this.AddTypeToModule(e);
     if (this.inUnsafeCode) this.HandleError(e.Name.SourceContext, Error.InvalidModifier, "unsafe");
   }
   TypeNode t = this.TypeExpressionFor(Token.Int);
   if (this.currentToken == Token.Colon){
     this.GetNextToken();
     switch(this.currentToken){
       case Token.Sbyte:
       case Token.Byte:
       case Token.Short:
       case Token.Ushort:
       case Token.Int:
       case Token.Uint:
       case Token.Long:
       case Token.Ulong:
         t = this.TypeExpressionFor(this.currentToken);
         this.GetNextToken();
         break;
       default:
         TypeNode tt = this.ParseTypeExpression(null, followers|Token.LeftBrace);
         if (tt != null)
           this.HandleError(tt.SourceContext, Error.IntegralTypeExpected);
         break;
     }
   }
   e.UnderlyingTypeExpression = t;
   e.SourceContext.EndPos = this.scanner.endPos;
   e.Documentation = this.LastDocComment;
   SourceContext typeBodyCtx = this.scanner.CurrentSourceContext;
   this.Skip(Token.LeftBrace);
   Field prevField = null;
   int offset = 0;
   while (this.currentToken != Token.RightBrace){
     if (this.currentToken == Token.SingleLineDocCommentStart || this.currentToken == Token.MultiLineDocCommentStart)
       this.ParseDocComment(followers|Parser.IdentifierOrNonReservedKeyword|Token.Comma|Token.RightBrace);
     SourceContext ctx = this.scanner.CurrentSourceContext;
     AttributeList attrs = this.ParseAttributes(null, followers|Parser.IdentifierOrNonReservedKeyword|Token.Comma|Token.RightBrace);
     Identifier id = this.scanner.GetIdentifier();
     this.SkipIdentifierOrNonReservedKeyword();
     Field f = new Field(e, attrs, FieldFlags.Public|FieldFlags.Literal|FieldFlags.Static|FieldFlags.HasDefault, id, e, null);
     e.Members.Add(f);
     f.Documentation = this.LastDocComment;
     f.SourceContext = ctx;
     if (this.currentToken == Token.Assign){
       this.GetNextToken();
       if (Parser.UnaryStart[this.currentToken])
         f.Initializer = this.ParseExpression(followers|Token.Comma|Token.RightBrace);
       else{
         this.SkipTo(followers|Token.Comma|Token.RightBrace, Error.ConstantExpected);
         f.Initializer = new Literal(offset++);
       }
       prevField = f;
     }else{
       if (prevField == null)
         f.Initializer = new Literal(offset++);
       else{
         f.Initializer = new BinaryExpression(new MemberBinding(null, prevField), new Literal(1), NodeType.Add, ctx);
         prevField = f;
       }
     }
     if (this.currentToken != Token.Comma){
       if (this.currentToken == Token.Semicolon){
         SourceContext sc = this.scanner.CurrentSourceContext;
         this.GetNextToken();
         if (Parser.IdentifierOrNonReservedKeyword[this.currentToken]){
           this.HandleError(sc, Error.SyntaxError, ",");
           continue;
         }else if (this.currentToken == Token.RightBrace){
           this.HandleError(sc, Error.ExpectedRightBrace);
           break;
         }
       }
       break;
     }
     this.GetNextToken();
   }
   int endCol = this.scanner.endPos;
   if (this.sink != null){
     typeBodyCtx.EndPos = this.scanner.endPos;
     this.sink.AddCollapsibleRegion(typeBodyCtx, false);
   }
   this.ParseBracket(e.SourceContext, Token.RightBrace, followers|Token.Semicolon, Error.ExpectedRightBrace);
   e.SourceContext.EndPos = endCol;
   if (this.currentToken == Token.Semicolon)
     this.GetNextToken();
   this.SkipTo(followers|Parser.TypeMemberStart);
   if (!followers[this.currentToken])
     this.SkipTo(followers, Error.NamespaceUnexpected);
 }
예제 #23
0
    private void ParseInvariant(TypeNode parentType, AttributeList attributes, TokenList modifierTokens, SourceContextList modifierContexts, SourceContext sctx, TokenSet followers){
      Debug.Assert(this.currentToken == Token.Invariant);
      bool savedParsingStatement = this.parsingStatement;
      if (this.currentToken != Token.EndOfFile) this.parsingStatement = true;

      for(int i = 0, n = modifierTokens.Length; i < n; i++){
        switch(modifierTokens[i]){
          case Token.Static: break;
          default:
           // Token.New, Token.Public, Token.Protected, Token.Internal, Token.Private, Token.Abstract,
           // Token.Sealed, Token.Readonly, Token.Volatile, Token.Virtual, Token.Override, Token.Extern,
           //Token.Unsafe
            this.HandleError(modifierContexts[i], Error.InvalidModifier, modifierContexts[i].SourceText);
            break;
        }
      }

      SourceContext sctxt = this.scanner.CurrentSourceContext;
      this.GetNextToken();
      Expression condition = this.ParseExpression(followers|Token.Semicolon);
      int endPos = this.scanner.endPos;
      this.SkipSemiColon(followers);

      if (!(parentType is Class || parentType is Struct)){
        this.HandleError(sctxt, Error.OnlyStructsAndClassesCanHaveInvariants);
        if (this.currentToken != Token.EndOfFile) this.parsingStatement = savedParsingStatement;
        return;
      }

      EnsureHasInvariantMethod(parentType);
      TypeContract contract = parentType.Contract;
      Identifier name = Identifier.For("invariant" + (InvariantCt++));
      Invariant inv = new Invariant(parentType, attributes, name);
      inv.SourceContext = sctxt;
      inv.Flags = this.GetMethodFlags(modifierTokens, modifierContexts, parentType, inv)|MethodFlags.HideBySig;

      if ((inv.Flags & MethodFlags.Static) != 0 && parentType is Interface){
        this.HandleError(sctx, Error.InvalidModifier, "static");
        inv.Flags &= ~MethodFlags.Static;
      }
      if ((inv.Flags & MethodFlags.Static) == 0)
        inv.CallingConvention = CallingConventionFlags.HasThis;
      inv.Documentation = this.LastDocComment;
      inv.SourceContext.EndPos = endPos;
      inv.Condition = condition;
      contract.Invariants.Add(inv);
      if (this.currentToken != Token.EndOfFile) this.parsingStatement = savedParsingStatement;
    }
예제 #24
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;
 }
예제 #25
0
 private void ParseTypeDeclaration(Namespace ns, TypeNode parentType, AttributeList attributes, TokenList modifierTokens,
   SourceContextList modifierContexts, TypeFlags flags, bool isPartial, SourceContext sctx, TokenSet followers){
   if (parentType is Interface){
     this.HandleError(Error.InterfacesCannotContainTypes);
     modifierTokens = null;
   }
   TypeNode t = null;
   InvariantCt = 0;
   switch(this.currentToken){
     case Token.Class:
       Class c = new Class();
       t = c;
       if (parentType == null)
         t.DeclaringNamespace = ns;
       else
         t.DeclaringType = parentType;
       if (modifierTokens != null)
         t.Flags |= this.NestedTypeFlags(modifierTokens, modifierContexts, t, isPartial)|TypeFlags.BeforeFieldInit;
       else{
         t.IsUnsafe = this.inUnsafeCode;
         t.Flags |= flags|TypeFlags.BeforeFieldInit;
       }
       if (t.IsAbstract && t.IsSealed && t.IsSpecialName){
         c.IsAbstractSealedContainerForStatics = true;
         c.Flags &= ~TypeFlags.SpecialName;
       }
       break;
     case Token.Interface:
       t = new Interface();
       if (parentType == null)
         t.DeclaringNamespace = ns;
       else
         t.DeclaringType = parentType;
       if (modifierTokens != null)
         t.Flags |= this.NestedTypeFlags(modifierTokens, modifierContexts, t, isPartial);
       else{
         if ((flags & TypeFlags.Abstract) != 0){
           if ((flags & TypeFlags.Sealed) != 0 && (flags & TypeFlags.SpecialName) != 0){
             this.HandleError(Error.InvalidModifier, "static");
             flags &= ~(TypeFlags.Abstract|TypeFlags.Sealed|TypeFlags.SpecialName);
           }else{
             this.HandleError(Error.InvalidModifier, "abstract");
             flags &= ~TypeFlags.Abstract;
           }
         }else if ((flags & TypeFlags.Sealed) != 0){
           this.HandleError(Error.InvalidModifier, "sealed");
           flags &= ~TypeFlags.Sealed;
         }
         t.IsUnsafe = this.inUnsafeCode;
         t.Flags |= flags|TypeFlags.BeforeFieldInit;
       }
       break;
     case Token.Struct:
       t = new Struct();
       if (parentType == null)
         t.DeclaringNamespace = ns;
       else
         t.DeclaringType = parentType;
       if (modifierTokens != null)
         t.Flags |= this.NestedTypeFlags(modifierTokens, modifierContexts, t, isPartial)|TypeFlags.BeforeFieldInit;
       else{
         if ((flags & TypeFlags.Abstract) != 0){
           if ((flags & TypeFlags.Sealed) != 0 && (flags & TypeFlags.SpecialName) != 0){
             this.HandleError(Error.InvalidModifier, "static");
             flags &= ~(TypeFlags.Abstract|TypeFlags.Sealed|TypeFlags.SpecialName);
           }else{
             this.HandleError(Error.InvalidModifier, "abstract");
             flags &= ~TypeFlags.Abstract;
           }
         }else if ((flags & TypeFlags.Sealed) != 0){
           this.HandleError(Error.InvalidModifier, "sealed");
         }
         t.IsUnsafe = this.inUnsafeCode;
         t.Flags |= flags|TypeFlags.BeforeFieldInit;
       }
       break;
     default:
       Debug.Assert(false);
       break;
   }
   t.Attributes = attributes;
   t.SourceContext = sctx;
   t.DeclaringModule = this.module;
   t.Documentation = this.LastDocComment;
   this.GetNextToken();
   t.Name = this.scanner.GetIdentifier();
   if (Parser.IdentifierOrNonReservedKeyword[this.currentToken])
     this.GetNextToken();
   else{
     this.SkipIdentifierOrNonReservedKeyword();
     if (Parser.IdentifierOrNonReservedKeyword[this.currentToken]){
       t.Name = this.scanner.GetIdentifier();
       this.GetNextToken();
     }
   }
   if (this.currentToken == Token.LessThan)
     this.ParseTypeParameters(t, followers|Token.Colon|Token.LeftBrace|Token.Where);
   if (parentType != null){
     t.Namespace = Identifier.Empty;
     if (parentType.IsGeneric) t.IsGeneric = true;
   }else
     t.Namespace = ns.FullNameId;
   Identifier mangledName = t.Name;
   if (Cci.TargetPlatform.GenericTypeNamesMangleChar != 0) {
     int numPars = t.TemplateParameters == null ? 0 : t.TemplateParameters.Count;
     if (numPars > 0){
       mangledName = new Identifier(t.Name.ToString() + Cci.TargetPlatform.GenericTypeNamesMangleChar + numPars.ToString(), t.Name.SourceContext);
       t.IsGeneric = this.useGenerics;
     }
   }
   t.PartiallyDefines = this.GetCompleteType(t, mangledName, isPartial);
   if (isPartial){
     isPartial = t.PartiallyDefines != null;
     if (!isPartial)
       t.Name = new Identifier(t.Name+" "+t.UniqueKey, t.Name.SourceContext);
   }else
     isPartial = t.PartiallyDefines != null;
   if (parentType != null){
     if (!isPartial || parentType.PartiallyDefines != null)
       parentType.Members.Add(t);
   }else{
     ns.Types.Add(t);
     if (!isPartial) this.AddTypeToModule(t);
   }
   if (this.currentToken == Token.Colon){
     this.GetNextToken();
     t.Interfaces = this.ParseInterfaceList(followers|Token.LeftBrace|Token.Where, true); //The first of these might be the base class, but that is a semantic issue
   }else
     t.Interfaces = new InterfaceList(); //TODO: omit this?
   t.InterfaceExpressions = t.Interfaces;
   while (this.currentToken == Token.Where)
     this.ParseTypeParameterConstraint(t, followers|Token.LeftBrace|Token.Where);
   t.SourceContext.EndPos = this.scanner.endPos;
   SourceContext typeBodyCtx = this.scanner.CurrentSourceContext;
   this.Skip(Token.LeftBrace);
 tryAgain:
   this.ParseTypeMembers(t, followers|Token.RightBrace);
   if (this.currentToken == Token.Namespace){
     this.HandleError(Error.InvalidMemberDecl, this.scanner.CurrentSourceContext.SourceText);
     this.currentToken = Token.Class;
     goto tryAgain;
   }
   int endCol = this.scanner.endPos;
   this.ParseBracket(t.SourceContext, Token.RightBrace, followers|Token.Semicolon, Error.ExpectedRightBrace);
   t.SourceContext.EndPos = endCol;
   t.Name = mangledName;
   if (this.currentToken == Token.Semicolon)
     this.GetNextToken();
   if (this.sink != null){
     typeBodyCtx.EndPos = endCol;
     this.sink.AddCollapsibleRegion(typeBodyCtx, false);
   }
   this.SkipTo(followers|Parser.TypeMemberStart);
   if (!followers[this.currentToken])
     this.SkipTo(followers, Error.NamespaceUnexpected);
   if (isPartial) this.MergeWithCompleteType(t);
 }
예제 #26
0
 private void ParseTypeMembers(TypeNode t, TokenSet followers){
   TokenSet followersOrTypeMemberStart = followers|Parser.TypeMemberStart;
   for(;;){
     SourceContext sctx = this.scanner.CurrentSourceContext;
     AttributeList attributes = this.ParseAttributes(null, followersOrTypeMemberStart);
     bool savedInUnsafeCode = this.inUnsafeCode;
     TokenList modifierTokens = new TokenList();
     SourceContextList modifierContexts = new SourceContextList();
     this.ParseModifiers(modifierTokens, modifierContexts, t.NodeType == NodeType.Interface);
     sctx.EndPos = this.scanner.endPos;
     switch(this.currentToken){
       case Token.Class:
       case Token.Struct:
       case Token.Interface:
         this.ParseTypeDeclaration(null, t, attributes, modifierTokens, modifierContexts, false, sctx, followersOrTypeMemberStart);
         break;
       case Token.Delegate:
         TypeNode del = this.ParseDelegateDeclaration(null, t, attributes, modifierTokens, modifierContexts, sctx, followersOrTypeMemberStart);
         if (del is FunctionTypeExpression){
           this.lastDocCommentBackingField = (XmlElement)del.Documentation;
           this.ParseFieldOrMethodOrPropertyOrStaticInitializer(del, t, attributes, modifierTokens, modifierContexts,
             sctx, this.scanner.CurrentSourceContext, followersOrTypeMemberStart);
         }
         break;
       case Token.Enum:
         this.ParseEnumDeclaration(null, t, attributes, modifierTokens, modifierContexts, sctx, followersOrTypeMemberStart);
         break;
       case Token.Const:
         this.ParseConst(t, attributes, modifierTokens, modifierContexts, sctx, followersOrTypeMemberStart);
         break;
       case Token.Invariant:
         this.ParseInvariant(t, attributes, modifierTokens, modifierContexts, sctx, followersOrTypeMemberStart);
         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:
       case Token.Void:
       case Token.Identifier:
         NotPartial:
           this.ParseFieldOrMethodOrPropertyOrStaticInitializer(t, attributes, modifierTokens, modifierContexts,
             sctx, followersOrTypeMemberStart);
         break;
       case Token.Model:
         this.GetNextToken();
         this.ParseModelField(t, attributes, modifierTokens, modifierContexts, sctx, followersOrTypeMemberStart);
         break;
       case Token.Event:
         this.ParseEvent(t, attributes, modifierTokens, modifierContexts, sctx, followersOrTypeMemberStart); break;
       case Token.Operator:
       case Token.Explicit:
       case Token.Implicit:
         this.ParseOperator(t, attributes, modifierTokens, modifierContexts, null, sctx, followersOrTypeMemberStart); break;
       case Token.BitwiseNot:
         this.ParseDestructor(t, attributes, modifierTokens, modifierContexts, sctx, followersOrTypeMemberStart); break;
       case Token.MultiLineDocCommentStart:
       case Token.SingleLineDocCommentStart:
         this.ParseDocComment(followersOrTypeMemberStart);
         break;
       case Token.Partial:
         SourceContext pctx = this.scanner.CurrentSourceContext;
         ScannerState ss = this.scanner.state;
         this.GetNextToken();
         switch (this.currentToken){
           case Token.Class:
           case Token.Struct:
           case Token.Interface:
             this.ParseTypeDeclaration(null, t, attributes, modifierTokens, modifierContexts, true, sctx, followersOrTypeMemberStart);
             break;
           case Token.Enum:
             this.HandleError(Error.PartialMisplaced);
             this.ParseEnumDeclaration(null, t, attributes, modifierTokens, modifierContexts, sctx, followersOrTypeMemberStart);
             break;
           case Token.LeftParenthesis:
           case Token.LeftBrace:
           case Token.LessThan:
             this.scanner.endPos = pctx.StartPos;
             this.scanner.state = ss;
             this.currentToken = Token.None;
             this.GetNextToken();
             goto NotPartial;
           default:
             if (Parser.IdentifierOrNonReservedKeyword[this.currentToken])
               goto case Token.LeftParenthesis;
             this.HandleError(Error.PartialMisplaced);
             this.SkipTo(followers, Error.None);
             return;
         }
         break;
       default:
         if (Parser.IdentifierOrNonReservedKeyword[this.currentToken]) goto case Token.Identifier;
         if (this.currentToken == Token.EndOfFile && this.sink != null){
           if (attributes != null){
             Class dummy = new Class(this.module, t, attributes, TypeFlags.Public, Identifier.Empty, Identifier.Empty, null, null, new MemberList(0));
             t.Members.Add(dummy);
           //}else{
           //  Field dummy = new Field(t, null, FieldFlags.Public, Identifier.Empty, new TypeExpression(new Identifier(" ", this.scanner.CurrentSourceContext)), null);
           //  t.Members.Add(dummy);
           }
         }
         return;
     }
     this.inUnsafeCode = savedInUnsafeCode;
   }
 }