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; }
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(); } }
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); }
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); }
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); }
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; }
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); } }
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); }
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; }
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; } }
/// <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 ; }
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); }
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; }
private TypeFlags NestedTypeFlags(TokenList modifierTokens, SourceContextList modifierContexts, Member ntype){ return this.NestedTypeFlags(modifierTokens, modifierContexts, ntype, false); }
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; }
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; }
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; }
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); }
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; } } }
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); } }
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; }
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); }
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; }
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; }
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); }
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; } }