private void ParseRestOfEnum(SourceLocationBuilder sctx, TypeDeclaration type, List<ITypeDeclarationMember> members, TokenSet followers) //^ ensures followers[this.currentToken] || this.currentToken == Token.EndOfFile; { TypeExpression texpr = new NamedTypeExpression(new SimpleName(type.Name, type.Name.SourceLocation, false)); this.Skip(Token.LeftBrace); while (this.currentToken == Token.LeftBracket || Parser.IdentifierOrNonReservedKeyword[this.currentToken]){ this.ParseEnumMember(texpr, members, followers|Token.Comma|Token.RightBrace); if (this.currentToken == Token.RightBrace) break; this.Skip(Token.Comma); if (this.currentToken == Token.RightBrace) break; } sctx.UpdateToSpan(this.scanner.SourceLocationOfLastScannedToken); this.Skip(Token.RightBrace); if (this.currentToken == Token.Semicolon) this.GetNextToken(); this.SkipTo(followers); }
private TypeExpression ParseBaseTypeExpression(bool allowEmptyArguments, TokenSet followers) //^ requires this.currentToken != Token.EndOfFile; //^ ensures followers[this.currentToken] || this.currentToken == Token.EndOfFile; { TypeExpression result; switch(this.currentToken){ 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: result = this.GetTypeExpressionFor(this.currentToken, this.scanner.SourceLocationOfLastScannedToken); this.GetNextToken(); this.SkipTo(followers); break; default: Expression expr = this.ParseNamespaceOrTypeName(allowEmptyArguments, followers); GenericTypeInstanceExpression/*?*/ gtexpr = expr as GenericTypeInstanceExpression; if (gtexpr != null) result = gtexpr; else result = new NamedTypeExpression(expr); break; } return result; }
private Expression ParseNamespaceOrTypeName(bool allowEmptyArguments, TokenSet followers) //^ ensures followers[this.currentToken] || this.currentToken == Token.EndOfFile; //^ ensures result is SimpleName || result is AliasQualifiedName || result is QualifiedName || result is GenericTypeInstanceExpression; { SimpleName rootName = this.ParseSimpleName(followers|Token.Dot|Token.DoubleColon|Token.LessThan); Expression expression = rootName; if (rootName.Name.UniqueKey == this.nameTable.global.UniqueKey && this.currentToken == Token.DoubleColon) expression = new RootNamespaceExpression(rootName.SourceLocation); SourceLocationBuilder sctx = new SourceLocationBuilder(expression.SourceLocation); if (this.currentToken == Token.DoubleColon) { this.GetNextToken(); SimpleName simpleName = this.ParseSimpleName(followers|Token.Dot|Token.LessThan); sctx.UpdateToSpan(simpleName.SourceLocation); expression = new AliasQualifiedName(expression, simpleName, sctx.GetSourceLocation()); } //^ assume expression is SimpleName || expression is AliasQualifiedName; //RootNamespace will always disappear into AliasQualifiedName moreDots: while (this.currentToken == Token.Dot) //^ invariant expression is SimpleName || expression is AliasQualifiedName || expression is QualifiedName || expression is GenericTypeInstanceExpression; { this.GetNextToken(); SimpleName simpleName = this.ParseSimpleName(followers|Token.Dot|Token.LessThan); sctx.UpdateToSpan(simpleName.SourceLocation); expression = new QualifiedName(expression, simpleName, sctx.GetSourceLocation()); } if (this.currentToken == Token.LessThan) { //^ assume expression is SimpleName || expression is AliasQualifiedName || expression is QualifiedName; //Can only get back here if generic instance was followed by dot. TypeExpression genericType = new NamedTypeExpression(expression); while (this.currentToken == Token.LessThan) //^ invariant expression is SimpleName || expression is AliasQualifiedName || expression is QualifiedName || expression is GenericTypeInstanceExpression; { List<TypeExpression> arguments = this.ParseTypeArguments(sctx, allowEmptyArguments, followers|Token.Dot); expression = new GenericTypeInstanceExpression(genericType, arguments.AsReadOnly(), sctx.GetSourceLocation()); } if (this.currentToken == Token.Dot) goto moreDots; } if (this.insideType && !this.insideBlock && !followers[this.currentToken]) this.SkipTo(followers, Error.InvalidMemberDecl, this.scanner.GetTokenSource()); else this.SkipTo(followers); return expression; }
private void ParseOperator(List<ITypeDeclarationMember> members, List<SourceCustomAttribute>/*?*/ attributes, List<ModifierToken> modifiers, TypeExpression/*?*/ resultType, SourceLocationBuilder sctx, TokenSet followers) //^ requires this.currentToken == Token.Explicit || this.currentToken == Token.Implicit || this.currentToken == Token.Operator; //^ ensures followers[this.currentToken] || this.currentToken == Token.EndOfFile; { MethodDeclaration.Flags flags = MethodDeclaration.Flags.SpecialName; TypeMemberVisibility visibility = this.ConvertToTypeMemberVisibility(modifiers); this.LookForModifier(modifiers, Token.Abstract, Error.InvalidModifier); if (this.LookForModifier(modifiers, Token.Extern, Error.None)) flags |= MethodDeclaration.Flags.External; this.LookForModifier(modifiers, Token.New, Error.InvalidModifier); this.LookForModifier(modifiers, Token.Override, Error.InvalidModifier); this.LookForModifier(modifiers, Token.Readonly, Error.InvalidModifier); this.LookForModifier(modifiers, Token.Sealed, Error.InvalidModifier); if (this.LookForModifier(modifiers, Token.Static, Error.None)) flags |= MethodDeclaration.Flags.Static; if (this.LookForModifier(modifiers, Token.Unsafe, Error.None)) flags |= MethodDeclaration.Flags.Unsafe; this.LookForModifier(modifiers, Token.Virtual, Error.InvalidModifier); this.LookForModifier(modifiers, Token.Volatile, Error.InvalidModifier); NameDeclaration opName = new NameDeclaration(this.nameTable.EmptyName, this.scanner.SourceLocationOfLastScannedToken); SourceLocationBuilder ctx = new SourceLocationBuilder(this.scanner.SourceLocationOfLastScannedToken); ISourceLocation symCtx = this.scanner.SourceLocationOfLastScannedToken; bool canBeBinary = false; bool canBeUnary = false; switch (this.currentToken) { case Token.Explicit: this.GetNextToken(); ctx.UpdateToSpan(this.scanner.SourceLocationOfLastScannedToken); opName = this.GetNameDeclarationFor("op_Explicit", ctx.GetSourceLocation()); this.Skip(Token.Operator); if (resultType != null && this.currentToken == Token.LeftParenthesis) this.HandleError(opName.SourceLocation, Error.BadOperatorSyntax, "explicit"); else resultType = this.ParseTypeExpression(false, false, followers|Token.LeftParenthesis); canBeUnary = true; break; case Token.Implicit: this.GetNextToken(); ctx.UpdateToSpan(this.scanner.SourceLocationOfLastScannedToken); opName = this.GetNameDeclarationFor("op_Implicit", ctx.GetSourceLocation()); this.Skip(Token.Operator); if (resultType != null && this.currentToken == Token.LeftParenthesis) this.HandleError(opName.SourceLocation, Error.BadOperatorSyntax, "implicit"); else resultType = this.ParseTypeExpression(false, false, followers|Token.LeftParenthesis); canBeUnary = true; break; case Token.Operator: this.GetNextToken(); symCtx = this.scanner.SourceLocationOfLastScannedToken; ctx.UpdateToSpan(symCtx); this.GetOperatorName(ref opName, ref canBeBinary, ref canBeUnary, ctx.GetSourceLocation()); if (this.currentToken != Token.EndOfFile) this.GetNextToken(); if (resultType == null) { this.HandleError(Error.BadOperatorSyntax2, ctx.GetSourceLocation().Source); if (this.currentToken != Token.LeftParenthesis) resultType = this.ParseTypeExpression(false, false, followers|Token.LeftParenthesis); else resultType = new NamedTypeExpression(this.RootQualifiedNameFor(Token.Void)); } break; default: //^ assert false; break; } //Parse the parameter list List<Ast.ParameterDeclaration> parameters = new List<Ast.ParameterDeclaration>(); this.ParseParameters(parameters, 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.Value == "op_Addition") opName = this.GetNameDeclarationFor("op_UnaryPlus", opName.SourceLocation); else if (opName.Value == "op_Subtraction") opName = this.GetNameDeclarationFor("op_UnaryNegation", opName.SourceLocation); } break; case 2: if (!canBeBinary) if (canBeUnary) this.HandleError(symCtx, Error.WrongParsForUnaryOp, opName.SourceLocation.Source); else this.HandleError(symCtx, Error.OvlBinaryOperatorExpected); break; default: if (canBeBinary) this.HandleError(symCtx, Error.WrongParsForBinOp, opName.SourceLocation.Source); else if (canBeUnary) this.HandleError(symCtx, Error.WrongParsForUnaryOp, opName.SourceLocation.Source); else this.HandleError(symCtx, Error.OvlBinaryOperatorExpected); break; } ctx.UpdateToSpan(this.scanner.SourceLocationOfLastScannedToken); //bool swallowedSemicolonAlready = false; //this.ParseMethodContract(oper, followers|Token.LeftBrace|Token.Semicolon, ref swallowedSemicolonAlready); BlockStatement body = this.ParseBody(followers); //^ assert followers[this.currentToken] || this.currentToken == Token.EndOfFile; sctx.UpdateToSpan(body.SourceLocation); MethodDeclaration method = new MethodDeclaration(attributes, flags, visibility, resultType, null, opName, null, parameters, null, body, sctx.GetSourceLocation()); members.Add(method); //^ assume followers[this.currentToken] || this.currentToken == Token.EndOfFile; }
private Expression ParseImplementedInterfacePlusName(ref NameDeclaration name, bool allowThis, TokenSet followers) //^ ensures result is SimpleName || result is QualifiedName; //^ ensures result is QualifiedName ==> (((QualifiedName)result).Qualifier is SimpleName || //^ ((QualifiedName)result).Qualifier is QualifiedName || ((QualifiedName)result).Qualifier is GenericTypeInstanceExpression); { Expression implementedInterface = new SimpleName(name, name.SourceLocation, false); while (this.currentToken == Token.Dot || this.currentToken == Token.LessThan) //^ invariant implementedInterface is SimpleName || implementedInterface is QualifiedName; //The following invariant does not hold, it seems. Fix it. //^ invariant implementedInterface is QualifiedName ==> (((QualifiedName)implementedInterface).Qualifier is SimpleName || //^ ((QualifiedName)implementedInterface).Qualifier is QualifiedName || ((QualifiedName)implementedInterface).Qualifier is GenericTypeInstanceExpression); { if (this.currentToken == Token.LessThan) { //^ assume implementedInterface is SimpleName || implementedInterface is QualifiedName; TypeExpression genericType = new NamedTypeExpression(implementedInterface); SourceLocationBuilder ctx = new SourceLocationBuilder(implementedInterface.SourceLocation); List<TypeExpression> typeArguments = this.ParseTypeArguments(ctx, false, followers|Token.Dot|Token.LeftBrace); implementedInterface = new GenericTypeInstanceExpression(genericType, typeArguments, ctx); } this.Skip(Token.Dot); if (this.currentToken == Token.This && allowThis) { name = this.GetNameDeclarationFor("Item", this.scanner.SourceLocationOfLastScannedToken); } else { if (!Parser.IdentifierOrNonReservedKeyword[this.currentToken]) this.SkipTo(followers|Parser.IdentifierOrNonReservedKeyword|Token.LeftBrace, Error.ExpectedIdentifier); name = this.ParseNameDeclaration(); } SourceLocationBuilder ctx1 = new SourceLocationBuilder(implementedInterface.SourceLocation); ctx1.UpdateToSpan(name.SourceLocation); implementedInterface = new QualifiedName(implementedInterface, new SimpleName(name, name.SourceLocation, false), ctx1); } return implementedInterface; }
private Statement ParseForEach(SourceLocationBuilder slb, TokenSet followers) //^ requires this.currentToken == Token.Each; //^ ensures followers[this.currentToken] || this.currentToken == Token.EndOfFile; { this.GetNextToken(); NameDeclaration variableName = this.ParseNameDeclaration(); this.Skip(Token.In); Expression collection = this.ParseExpression(followers|Token.EndOfLine); this.Skip(Token.EndOfLine); BlockStatement body = this.ParseStatementBlock(followers|Token.Next); slb.UpdateToSpan(body.SourceLocation); TypeExpression variableType = new NamedTypeExpression(new SimpleName(this.nameTable.GetNameFor("var"), SourceDummy.SourceLocation, false)); ForEachStatement result = new ForEachStatement(variableType, variableName, collection, body, slb); this.SkipClosingKeyword(Token.Next, followers); return result; }