private GetSourceLocation ( ) : ISourceLocation | ||
Résultat | ISourceLocation |
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 NamespaceReferenceExpression ParseImportedNamespaceName(NameDeclaration name, TokenSet followers) //^ ensures followers[this.currentToken] || this.currentToken == Token.EndOfFile; { Expression expression = new SimpleName(name, name.SourceLocation, false); SourceLocationBuilder sctx = new SourceLocationBuilder(expression.SourceLocation); if (this.currentToken == Token.DoubleColon) { this.GetNextToken(); SimpleName simpleName = this.ParseSimpleName(followers|Token.Dot); sctx.UpdateToSpan(simpleName.SourceLocation); expression = new AliasQualifiedName(expression, simpleName, sctx.GetSourceLocation()); } while (this.currentToken == Token.Dot) //^ invariant expression is SimpleName || expression is QualifiedName || expression is AliasQualifiedName; { this.GetNextToken(); SimpleName simpleName = this.ParseSimpleName(followers|Token.Dot); sctx.UpdateToSpan(simpleName.SourceLocation); expression = new QualifiedName(expression, simpleName, sctx.GetSourceLocation()); } NamespaceReferenceExpression result = new NamespaceReferenceExpression(expression, sctx.GetSourceLocation()); this.SkipTo(followers); return result; }
private void ParseProperty(List<ITypeDeclarationMember> members, List<SourceCustomAttribute>/*?*/ attributes, List<ModifierToken> modifiers, TypeExpression type, List<TypeExpression>/*?*/ implementedInterfaces, NameDeclaration name, SourceLocationBuilder sctx, TokenSet followers) //^ requires (this.currentToken == Token.This && name.Value == "Item") || this.currentToken == Token.LeftBrace; //^ ensures followers[this.currentToken] || this.currentToken == Token.EndOfFile; { PropertyDeclaration.Flags flags = 0; TypeMemberVisibility visibility = this.ConvertToTypeMemberVisibility(modifiers); if (this.LookForModifier(modifiers, Token.Abstract, Error.None)) flags |= PropertyDeclaration.Flags.Abstract; if (this.LookForModifier(modifiers, Token.New, Error.None)) flags |= PropertyDeclaration.Flags.New; if (this.LookForModifier(modifiers, Token.Extern, Error.None)) flags |= PropertyDeclaration.Flags.External; if (this.LookForModifier(modifiers, Token.Override, Error.None)) flags |= PropertyDeclaration.Flags.Override; this.LookForModifier(modifiers, Token.Readonly, Error.InvalidModifier); if (this.LookForModifier(modifiers, Token.Sealed, Error.None)) flags |= PropertyDeclaration.Flags.Sealed; if (this.LookForModifier(modifiers, Token.Static, Error.None)) flags |= PropertyDeclaration.Flags.Static; if (this.LookForModifier(modifiers, Token.Unsafe, Error.None)) flags |= PropertyDeclaration.Flags.Unsafe; if (this.LookForModifier(modifiers, Token.Virtual, Error.None)) flags |= PropertyDeclaration.Flags.Virtual; this.LookForModifier(modifiers, Token.Volatile, Error.InvalidModifier); bool isIndexer = this.currentToken == Token.This; this.GetNextToken(); List<Ast.ParameterDeclaration>/*?*/ parameters = null; if (isIndexer) { parameters = new List<Ast.ParameterDeclaration>(); this.ParseParameters(parameters, Token.RightBracket, followers|Token.LeftBrace); this.Skip(Token.LeftBrace); } //if (this.currentToken == Token.LeftBrace) // this.GetNextToken(); //else { // Error e = Error.ExpectedLeftBrace; // if (implementedInterfaces != null) e = Error.ExplicitEventFieldImpl; // this.SkipTo(followers|Token.LeftBracket|Token.Add|Token.Remove|Token.RightBrace, e); //} TokenSet followersOrRightBrace = followers|Token.RightBrace; List<SourceCustomAttribute>/*?*/ getterAttributes = null; TypeMemberVisibility getterVisibility = visibility; BlockStatement/*?*/ getterBody = null; List<SourceCustomAttribute>/*?*/ setterAttributes = null; BlockStatement/*?*/ setterBody = null; TypeMemberVisibility setterVisibility = visibility; bool alreadyComplainedAboutModifier = false; List<ModifierToken>/*?*/ accessorModifiers = null; SourceLocationBuilder/*?*/ bodyCtx = null; for (; ; ) { if (bodyCtx == null) bodyCtx = new SourceLocationBuilder(this.scanner.SourceLocationOfLastScannedToken); List<SourceCustomAttribute>/*?*/ accessorAttrs = this.ParseAttributes(followers | Parser.GetOrLeftBracketOrSetOrModifier | Token.LeftBrace); switch (this.currentToken) { case Token.Get: if (accessorModifiers != null) { getterVisibility = this.ConvertToTypeMemberVisibility(accessorModifiers); accessorModifiers = null; } getterAttributes = accessorAttrs; if (getterBody != null) this.HandleError(Error.DuplicateAccessor); this.GetNextToken(); bool bodyAllowed = true; if (this.currentToken == Token.Semicolon) { this.GetNextToken(); bodyAllowed = false; } //this.ParseMethodContract(m, followers|Token.LeftBrace|Token.Semicolon, ref swallowedSemicolonAlready); if (bodyAllowed) getterBody = this.ParseBody(bodyCtx, followersOrRightBrace|Token.Set); bodyCtx = null; continue; case Token.Set: if (accessorModifiers != null) { setterVisibility = this.ConvertToTypeMemberVisibility(accessorModifiers); accessorModifiers = null; } setterAttributes = accessorAttrs; if (setterBody != null) this.HandleError(Error.DuplicateAccessor); this.GetNextToken(); bodyAllowed = true; if (this.currentToken == Token.Semicolon) { this.GetNextToken(); bodyAllowed = false; } //this.ParseMethodContract(m, followers|Token.LeftBrace|Token.Semicolon, ref swallowedSemicolonAlready); if (bodyAllowed) setterBody = this.ParseBody(bodyCtx, followersOrRightBrace|Token.Get); bodyCtx = null; continue; case Token.Protected: case Token.Internal: case Token.Private: if (accessorModifiers != null) goto case Token.Public; accessorModifiers = this.ParseModifiers(); continue; 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: if (!alreadyComplainedAboutModifier) this.HandleError(Error.NoModifiersOnAccessor); this.GetNextToken(); alreadyComplainedAboutModifier = true; continue; case Token.RightBrace: break; default: this.HandleError(Error.GetOrSetExpected); break; } break; } sctx.UpdateToSpan(bodyCtx.GetSourceLocation()); PropertyDeclaration prop = new PropertyDeclaration(attributes, flags, visibility, type, implementedInterfaces, name, parameters, getterAttributes, getterBody, getterVisibility, setterAttributes, setterBody, setterVisibility, sctx.GetSourceLocation()); members.Add(prop); this.SkipOverTo(Token.RightBrace, followers); }
private void ParseUsingDirective(List<INamespaceDeclarationMember> members, TokenSet followers) //^ requires this.currentToken == Token.Using; //^ ensures followers[this.currentToken] || this.currentToken == Token.EndOfFile; { SourceLocationBuilder sctx = new SourceLocationBuilder(this.scanner.SourceLocationOfLastScannedToken); this.GetNextToken(); if (!Parser.IdentifierOrNonReservedKeyword[this.currentToken]) { this.SkipTo(followers, Error.ExpectedIdentifier); return; } NameDeclaration name = this.ParseNameDeclaration(); TokenSet followersOrSemicolon = followers|Token.Semicolon; if (this.currentToken == Token.Assign) { this.GetNextToken(); Expression referencedNamespaceOrType = this.ParseNamespaceOrTypeName(false, followersOrSemicolon); sctx.UpdateToSpan(referencedNamespaceOrType.SourceLocation); members.Add(new AliasDeclaration(name, referencedNamespaceOrType, sctx.GetSourceLocation())); } else { NamespaceReferenceExpression namespaceName = this.ParseImportedNamespaceName(name, followersOrSemicolon); sctx.UpdateToSpan(namespaceName.SourceLocation); NameDeclaration dummyName = new NameDeclaration(Dummy.Name, this.scanner.SourceLocationOfLastScannedToken); members.Add(new NamespaceImportDeclaration(dummyName, namespaceName, sctx.GetSourceLocation())); } this.SkipSemiColon(followers); }
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 TypeExpression ParseArrayType(uint rank, TypeExpression elementType, SourceLocationBuilder sctx, TokenSet followers) //^ requires rank > 0; //^ ensures followers[this.currentToken] || this.currentToken == Token.EndOfFile; { List<uint> rankList = new List<uint>(); for (;;) // ^ invariant forall{int i in (0:rankList.Count); rankList[i] > 0}; //TODO: find out why this does not parse { rankList.Add(rank); //TODO: find away to tell Boogie that this does not modify this.currentToken if (this.currentToken != Token.LeftBracket) break; rank = this.ParseRankSpecifier(sctx, followers|Token.LeftBracket); } for (int i = rankList.Count; i > 0; i--) // ^ invariant forall{int i in (0:rankList.Count); rankList[i] > 0}; { rank = rankList[i-1]; //^ assume rank > 0; elementType = new ArrayTypeExpression(elementType, rank, sctx.GetSourceLocation()); //TODO: find away to tell Boogie that this does not modify this.currentToken } //^ assume followers[this.currentToken] || this.currentToken == Token.EndOfFile; return elementType; }
private Expression ParseSpecCastExpression(TokenSet followers, bool savedInSpecCode, SourceLocationBuilder slb) { if (this.CurrentTokenStartsTypeExpression()) { TypeExpression targetType = this.ParseTypeExpression(followers | Token.RightParenthesis); this.SkipOutOfSpecBlock(savedInSpecCode, TS.UnaryStart | followers); var valueToCast = this.ParseUnaryExpression(followers); slb.UpdateToSpan(valueToCast.SourceLocation); return new VccCast(valueToCast, targetType, slb); } if (this.currentToken == Token.Unchecked) { this.GetNextToken(); this.SkipOutOfSpecBlock(savedInSpecCode, TS.UnaryStart | followers); var uncheckedExpr = this.ParseUnaryExpression(followers); slb.UpdateToSpan(uncheckedExpr.SourceLocation); return new UncheckedExpression(uncheckedExpr, slb); } if (this.currentToken == Token.Identifier) { var id = this.scanner.GetIdentifierString(); //if (id.StartsWith("\\") && this.castlikeFunctions.ContainsKey(id.Substring(1))) // id = id.Substring(1); if (id == "atomic_op" || this.castlikeFunctions.ContainsKey(id)) { var methodName = id == "atomic_op" ? "" : this.castlikeFunctions[id]; var savedResultIsKeyword = this.resultIsAKeyword; this.resultIsAKeyword = (id == "atomic_op"); var isVarArgs = methodName.StartsWith("\\castlike_va_"); this.GetNextToken(); List<Expression> exprs = this.currentToken == Token.RightParenthesis ? new List<Expression>() : this.ParseExpressionList(Token.Comma, followers | Token.RightParenthesis); this.resultIsAKeyword = savedResultIsKeyword; this.SkipOutOfSpecBlock(savedInSpecCode, TS.UnaryStart | followers); if (isVarArgs) { slb.UpdateToSpan(this.scanner.SourceLocationOfLastScannedToken); var argList = new VccMethodCall(this.GetSimpleNameFor("\\argument_tuple"), exprs.ToArray(), slb.GetSourceLocation()); exprs.Clear(); exprs.Add(argList); } var expr = this.ParseUnaryExpression(followers); slb.UpdateToSpan(expr.SourceLocation); if (id == "atomic_op") { exprs.Add(expr); var atomicOp = new VccAtomicOp(this.GetSimpleNameFor("_vcc_atomic_op"), exprs.AsReadOnly(), slb); var atomicOpBlock = new VccAtomicOpBlock(new List<Statement>(0), atomicOp, slb); return new BlockExpression(atomicOpBlock, atomicOp, slb); } exprs.Insert(0, expr); return new VccMethodCall(this.GetSimpleNameFor(methodName), exprs, slb); } this.HandleError(Error.SyntaxError, this.scanner.GetTokenSource()); this.SkipOutOfSpecBlock(savedInSpecCode, followers); return new DummyExpression(slb); } this.HandleError(Error.SyntaxError, this.scanner.GetTokenSource()); this.SkipOutOfSpecBlock(savedInSpecCode, followers); return new DummyExpression(slb); }
private void ParseConst(List<ITypeDeclarationMember> members, List<SourceCustomAttribute>/*?*/ attributes, List<ModifierToken> modifiers, SourceLocationBuilder sctx, TokenSet followers) //^ requires this.currentToken == Token.Const; //^ ensures followers[this.currentToken] || this.currentToken == Token.EndOfFile; { this.GetNextToken(); TypeMemberVisibility visibility = this.ConvertToTypeMemberVisibility(modifiers); this.LookForModifier(modifiers, Token.Abstract, Error.InvalidModifier); this.LookForModifier(modifiers, Token.Extern, Error.InvalidModifier); bool isNew = this.LookForModifier(modifiers, Token.New, Error.None); this.LookForModifier(modifiers, Token.Override, Error.InvalidModifier); this.LookForModifier(modifiers, Token.Readonly, Error.InvalidModifier); this.LookForModifier(modifiers, Token.Sealed, Error.InvalidModifier); this.LookForModifier(modifiers, Token.Static, Error.StaticConstant); this.LookForModifier(modifiers, Token.Unsafe, Error.InvalidModifier); this.LookForModifier(modifiers, Token.Virtual, Error.InvalidModifier); this.LookForModifier(modifiers, Token.Volatile, Error.InvalidModifier); TokenSet followersOrCommaOrSemiColon = followers|Token.Comma|Token.Semicolon; TypeExpression type = this.ParseTypeExpression(false, false, followersOrCommaOrSemiColon|Parser.IdentifierOrNonReservedKeyword|Token.Assign); for (;;){ if (!Parser.IdentifierOrNonReservedKeyword[this.currentToken]) this.SkipTo(followers|Parser.IdentifierOrNonReservedKeyword|Token.Assign|Token.Comma|Token.Semicolon, Error.ExpectedIdentifier); NameDeclaration name = this.ParseNameDeclaration(); if (this.currentToken == Token.Assign) this.GetNextToken(); else if (this.currentToken == Token.LeftBrace && type is IInterfaceDeclaration) { //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(members, attributes, modifiers, type, null, name, sctx, followers); this.SkipOverTo(Token.LeftBrace, followers); return; } else { this.SkipTo(Parser.UnaryStart|followersOrCommaOrSemiColon, Error.ConstValueRequired); if (this.currentToken == Token.Comma) { this.GetNextToken(); continue; //Try to parse the next constant declarator } if (!Parser.UnaryStart[this.currentToken]) { this.SkipTo(followers, Error.None); return; } } Expression initializer = this.ParseExpression(followersOrCommaOrSemiColon); SourceLocationBuilder ctx = new SourceLocationBuilder(sctx.GetSourceLocation()); ctx.UpdateToSpan(initializer.SourceLocation); FieldDeclaration.Flags flags = FieldDeclaration.Flags.Constant|FieldDeclaration.Flags.Static; if (isNew) flags |= FieldDeclaration.Flags.New; FieldDeclaration f = new FieldDeclaration(attributes, flags, visibility, type, name, initializer, ctx.GetSourceLocation()); members.Add(f); if (this.currentToken != Token.Comma) break; this.GetNextToken(); } this.SkipSemiColon(followers); this.SkipTo(followers); }
private void ParseDestructor(IName parentTypeName, List<ITypeDeclarationMember> members, List<SourceCustomAttribute>/*?*/ attributes, List<ModifierToken> modifiers, SourceLocationBuilder sctx, TokenSet followers) //^ requires this.currentToken == Token.BitwiseNot; //^ ensures followers[this.currentToken] || this.currentToken == Token.EndOfFile; { this.GetNextToken(); MethodDeclaration.Flags flags = MethodDeclaration.Flags.SpecialName; this.LookForModifier(modifiers, Token.Abstract, Error.InvalidModifier); this.LookForModifier(modifiers, Token.New, Error.InvalidModifier); if (this.LookForModifier(modifiers, Token.Extern, Error.None)) flags |= MethodDeclaration.Flags.External; this.LookForModifier(modifiers, Token.Override, Error.InvalidModifier); this.LookForModifier(modifiers, Token.Readonly, Error.InvalidModifier); this.LookForModifier(modifiers, Token.Sealed, Error.InvalidModifier); this.LookForModifier(modifiers, Token.Static, Error.InvalidModifier); this.LookForModifier(modifiers, Token.Unsafe, Error.InvalidModifier); this.LookForModifier(modifiers, Token.Virtual, Error.InvalidModifier); this.LookForModifier(modifiers, Token.Volatile, Error.InvalidModifier); if (!Parser.IdentifierOrNonReservedKeyword[this.currentToken]) this.HandleError(Error.ExpectedIdentifier); NameDeclaration name = this.ParseNameDeclaration(); if (name.UniqueKey != parentTypeName.UniqueKey) this.HandleError(Error.WrongNameForDestructor); name = new NameDeclaration(this.GetNameFor("Finalize"), name.SourceLocation); List<Ast.ParameterDeclaration> parameters = new List<Ast.ParameterDeclaration>(0); this.ParseParameters(parameters, Token.RightParenthesis, followers|Token.LeftBrace); if (parameters.Count > 0) { this.HandleError(parameters[0].SourceLocation, Error.ExpectedRightParenthesis); parameters.Clear(); } BlockStatement body = this.ParseBody(followers); //^ assert followers[this.currentToken] || this.currentToken == Token.EndOfFile; sctx.UpdateToSpan(body.SourceLocation); MethodDeclaration method = new MethodDeclaration(attributes, flags, TypeMemberVisibility.Private, this.GetTypeExpressionFor(Token.Void, name.SourceLocation), null, name, null, parameters, null, body, sctx.GetSourceLocation()); members.Add(method); //^ assume followers[this.currentToken] || this.currentToken == Token.EndOfFile; }
private void ParseEventWithAccessors(List<ITypeDeclarationMember> members, List<SourceCustomAttribute>/*?*/ attributes, List<ModifierToken> modifiers, TypeExpression type, NameDeclaration name, SourceLocationBuilder sctx, TokenSet followers) //^ requires this.currentToken == Token.Dot || this.currentToken == Token.LessThan || this.currentToken == Token.LeftBrace; //^ ensures followers[this.currentToken] || this.currentToken == Token.EndOfFile; { EventDeclaration.Flags flags = 0; TypeMemberVisibility visibility = this.ConvertToTypeMemberVisibility(modifiers); if (this.LookForModifier(modifiers, Token.Abstract, Error.None)) flags |= EventDeclaration.Flags.Abstract; if (this.LookForModifier(modifiers, Token.New, Error.None)) flags |= EventDeclaration.Flags.New; if (this.LookForModifier(modifiers, Token.Extern, Error.None)) flags |= EventDeclaration.Flags.External; if (this.LookForModifier(modifiers, Token.Override, Error.None)) flags |= EventDeclaration.Flags.Override; this.LookForModifier(modifiers, Token.Readonly, Error.InvalidModifier); if (this.LookForModifier(modifiers, Token.Sealed, Error.None)) flags |= EventDeclaration.Flags.Sealed; if (this.LookForModifier(modifiers, Token.Static, Error.None)) flags |= EventDeclaration.Flags.Static; if (this.LookForModifier(modifiers, Token.Unsafe, Error.None)) flags |= EventDeclaration.Flags.Unsafe; if (this.LookForModifier(modifiers, Token.Virtual, Error.None)) flags |= EventDeclaration.Flags.Virtual; this.LookForModifier(modifiers, Token.Volatile, Error.InvalidModifier); List<TypeExpression>/*?*/ implementedInterfaces = null; Expression implementedInterface = this.ParseImplementedInterfacePlusName(ref name, false, followers); QualifiedName/*?*/ qual = implementedInterface as QualifiedName; if (qual != null) { implementedInterfaces = new List<TypeExpression>(1); GenericTypeInstanceExpression/*?*/ gte = qual.Qualifier as GenericTypeInstanceExpression; if (gte != null) implementedInterfaces.Add(gte); else { //^ assume qual.Qualifier is SimpleName || qual.Qualifier is QualifiedName; //follows from post condition of ParseImplementedInterfacePlusName implementedInterfaces.Add(new NamedTypeExpression(qual.Qualifier)); } } if (this.currentToken == Token.LeftBrace) this.GetNextToken(); else{ Error e = Error.ExpectedLeftBrace; if (implementedInterfaces != null) e = Error.ExplicitEventFieldImpl; this.SkipTo(followers|Token.LeftBracket|Token.Add|Token.Remove|Token.RightBrace, e); } TokenSet followersOrRightBrace = followers|Token.RightBrace; List<SourceCustomAttribute>/*?*/ adderAttributes = null; BlockStatement/*?*/ adderBody = null; List<SourceCustomAttribute>/*?*/ removerAttributes = null; BlockStatement/*?*/ removerBody = null; bool alreadyComplainedAboutModifier = false; for (; ; ) { List<SourceCustomAttribute>/*?*/ accessorAttrs = this.ParseAttributes(followers|Parser.AddOrRemoveOrModifier|Token.LeftBrace); switch (this.currentToken) { case Token.Add: adderAttributes = accessorAttrs; if (adderBody != null) this.HandleError(Error.DuplicateAccessor); this.GetNextToken(); if (this.currentToken != Token.LeftBrace) { this.SkipTo(followersOrRightBrace|Token.Remove, Error.AddRemoveMustHaveBody); } else adderBody = this.ParseBody(followersOrRightBrace|Token.Remove); continue; case Token.Remove: removerAttributes = accessorAttrs; if (removerBody != null) this.HandleError(Error.DuplicateAccessor); this.GetNextToken(); if (this.currentToken != Token.LeftBrace) { this.SkipTo(followersOrRightBrace|Token.Remove, Error.AddRemoveMustHaveBody); removerBody = null; } else removerBody = this.ParseBody(followersOrRightBrace|Token.Add); 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: if (!alreadyComplainedAboutModifier) this.HandleError(Error.NoModifiersOnAccessor); this.GetNextToken(); alreadyComplainedAboutModifier = true; continue; default: this.HandleError(Error.AddOrRemoveExpected); break; } break; } if (adderBody == null) adderBody = null; if (removerBody == null) removerBody = null; EventDeclaration evnt = new EventDeclaration(attributes, flags, visibility, type, implementedInterfaces, name, adderAttributes, adderBody, removerAttributes, removerBody, sctx.GetSourceLocation()); members.Add(evnt); this.SkipOverTo(Token.RightBrace, followers); }
private void ParseExternalAliasDirective(List<INamespaceDeclarationMember> members, TokenSet followers) //^ requires this.currentToken == Token.Extern; //^ ensures followers[this.currentToken] || this.currentToken == Token.EndOfFile; { SourceLocationBuilder sctx = new SourceLocationBuilder(this.scanner.SourceLocationOfLastScannedToken); this.GetNextToken(); if (this.currentToken == Token.Alias) this.GetNextToken(); else { if (!Parser.IdentifierOrNonReservedKeyword[this.currentToken]) { this.SkipTo(followers, Error.SyntaxError, "alias"); return; } this.HandleError(Error.SyntaxError, "alias"); } if (!Parser.IdentifierOrNonReservedKeyword[this.currentToken]) { this.SkipTo(followers, Error.ExpectedIdentifier); return; } NameDeclaration name = this.ParseNameDeclaration(); sctx.UpdateToSpan(this.scanner.SourceLocationOfLastScannedToken); members.Add(new UnitSetAliasDeclaration(name, sctx.GetSourceLocation())); this.SkipSemiColon(followers); }
private void ParseEvent(List<ITypeDeclarationMember> members, List<SourceCustomAttribute>/*?*/ attributes, List<ModifierToken> modifiers, SourceLocationBuilder sctx, TokenSet followers) //^ requires this.currentToken == Token.Event; //^ ensures followers[this.currentToken] || this.currentToken == Token.EndOfFile; { this.GetNextToken(); EventDeclaration.Flags flags = 0; TypeMemberVisibility visibility = this.ConvertToTypeMemberVisibility(modifiers); if (this.LookForModifier(modifiers, Token.Abstract, Error.None)) flags |= EventDeclaration.Flags.Abstract; if (this.LookForModifier(modifiers, Token.New, Error.None)) flags |= EventDeclaration.Flags.New; if (this.LookForModifier(modifiers, Token.Extern, Error.None)) flags |= EventDeclaration.Flags.External; if (this.LookForModifier(modifiers, Token.Override, Error.None)) flags |= EventDeclaration.Flags.Override; this.LookForModifier(modifiers, Token.Readonly, Error.InvalidModifier); if (this.LookForModifier(modifiers, Token.Sealed, Error.None)) flags |= EventDeclaration.Flags.Sealed; if (this.LookForModifier(modifiers, Token.Static, Error.None)) flags |= EventDeclaration.Flags.Static; if (this.LookForModifier(modifiers, Token.Unsafe, Error.None)) flags |= EventDeclaration.Flags.Unsafe; if (this.LookForModifier(modifiers, Token.Virtual, Error.None)) flags |= EventDeclaration.Flags.Virtual; this.LookForModifier(modifiers, Token.Volatile, Error.InvalidModifier); TokenSet followersOrCommaOrSemiColon = followers|Token.Comma|Token.Semicolon; TypeExpression type = this.ParseTypeExpression(false, false, followersOrCommaOrSemiColon|Parser.IdentifierOrNonReservedKeyword|Token.Assign); for (bool firstTime = true; ; firstTime = false){ if (!Parser.IdentifierOrNonReservedKeyword[this.currentToken]) this.SkipTo(followers|Parser.IdentifierOrNonReservedKeyword|Token.LeftBrace|Token.Dot|Token.LessThan|Token.Assign|Token.Comma, Error.ExpectedIdentifier); NameDeclaration name = this.ParseNameDeclaration(); if (firstTime && (this.currentToken == Token.LeftBrace || this.currentToken == Token.Dot || this.currentToken == Token.LessThan)) { this.ParseEventWithAccessors(members, attributes, modifiers, type, name, sctx, followers); return; } Expression/*?*/ initializer = null; if (this.currentToken == Token.Assign){ this.GetNextToken(); initializer = this.ParseExpression(followersOrCommaOrSemiColon); } SourceLocationBuilder ctx = new SourceLocationBuilder(sctx.GetSourceLocation()); if (initializer != null) ctx.UpdateToSpan(initializer.SourceLocation); else ctx.UpdateToSpan(name.SourceLocation); EventDeclaration e = new EventDeclaration(attributes, flags, visibility, type, name, initializer, ctx); members.Add(e); if (this.currentToken != Token.Comma) break; this.GetNextToken(); } this.SkipSemiColon(followers); this.SkipTo(followers); }
private LocalDeclarationsStatement ParseLocalDeclarations(SourceLocationBuilder slb, TypeExpression/*?*/ typeExpression, bool constant, bool initOnly, bool skipSemicolon, TokenSet followers) //^ ensures followers[this.currentToken] || this.currentToken == Token.EndOfFile; { var typeLocation = slb.GetSourceLocation(); List<LocalDeclaration> declarations = new List<LocalDeclaration>(); for (; ; ) { NameDeclaration locName = this.ParseNameDeclaration(); SourceLocationBuilder locSctx = new SourceLocationBuilder(locName.SourceLocation); //if (this.currentToken == Token.LeftBracket) { // this.HandleError(Error.CStyleArray); // int endPos = this.scanner.endPos; // int rank = this.ParseRankSpecifier(true, followers|Token.RightBracket|Parser.IdentifierOrNonReservedKeyword|Token.Assign|Token.Semicolon|Token.Comma); // if (rank > 0) // t = result.Type = result.TypeExpression = // this.ParseArrayType(rank, t, followers|Token.RightBracket|Parser.IdentifierOrNonReservedKeyword|Token.Assign|Token.Semicolon|Token.Comma); // else { // this.currentToken = Token.LeftBracket; // this.scanner.endPos = endPos; // this.GetNextToken(); // while (!this.scanner.TokenIsFirstAfterLineBreak && // this.currentToken != Token.RightBracket && this.currentToken != Token.Assign && this.currentToken != Token.Semicolon) // this.GetNextToken(); // if (this.currentToken == Token.RightBracket) this.GetNextToken(); // } //} //if (this.currentToken == Token.LeftParenthesis) { // this.HandleError(Error.BadVarDecl); // int dummy; // SourceContext lpCtx = this.scanner.CurrentSourceContext; // this.GetNextToken(); // this.ParseArgumentList(followers|Token.LeftBrace|Token.Semicolon|Token.Comma, lpCtx, out dummy); //} else Expression/*?*/ locInitialValue = null; if (this.currentToken == Token.Assign || constant) { this.Skip(Token.Assign); ArrayTypeExpression/*?*/ arrayTypeExpression = typeExpression as ArrayTypeExpression; if (this.currentToken == Token.LeftBrace && arrayTypeExpression != null) locInitialValue = this.ParseArrayInitializer(arrayTypeExpression, followers|Token.Semicolon|Token.Comma); else locInitialValue = this.ParseExpression(followers|Token.Semicolon|Token.Comma); } locSctx.UpdateToSpan(this.scanner.SourceLocationOfLastScannedToken); if (declarations.Count == 0) locSctx.UpdateToSpan(typeLocation); slb.UpdateToSpan(this.scanner.SourceLocationOfLastScannedToken); declarations.Add(new LocalDeclaration(false, false, locName, locInitialValue, locSctx)); if (this.currentToken != Token.Comma) break; this.GetNextToken(); //SourceContext sctx = this.scanner.CurrentSourceContext; //ScannerState ss = this.scanner.state; //TypeNode ty = this.ParseTypeExpression(null, followers|Token.Identifier|Token.Comma|Token.Semicolon, true); //if (ty == null || this.currentToken != Token.Identifier) { // this.scanner.endPos = sctx.StartPos; // this.scanner.state = ss; // this.currentToken = Token.None; // this.GetNextToken(); //} else // this.HandleError(sctx, Error.MultiTypeInDeclaration); } if (skipSemicolon) this.SkipSemiColon(followers); declarations.TrimExcess(); LocalDeclarationsStatement result = new LocalDeclarationsStatement(constant, initOnly, typeExpression == null, typeExpression, declarations, slb); this.SkipTo(followers); return result; }
private Statement ParseGoto(TokenSet followers) //^ requires this.currentToken == Token.Goto; //^ ensures followers[this.currentToken] || this.currentToken == Token.EndOfFile; { SourceLocationBuilder slb = new SourceLocationBuilder(this.scanner.CurrentSourceLocation); this.GetNextToken(); SimpleName targetLabel = this.ParseSimpleName(followers|Token.EndOfLine|Token.If); Statement result = new GotoStatement(targetLabel, slb); slb.UpdateToSpan(targetLabel.SourceLocation); if (this.currentToken == Token.If) { this.GetNextToken(); slb = new SourceLocationBuilder(slb.GetSourceLocation()); Expression condition = this.ParseExpression(followers|Token.EndOfLine); slb.UpdateToSpan(condition.SourceLocation); result = new ConditionalStatement(condition, result, new EmptyStatement(false, this.scanner.CurrentSourceLocation), slb); } this.SkipOverTo(Token.EndOfLine, followers); return result; }
private CatchClause ParseCatchClause(TokenSet followers, ref bool seenEmptyCatch) //^ requires this.currentToken == Token.Catch; //^ ensures followers[this.currentToken] || this.currentToken == Token.EndOfFile; { if (seenEmptyCatch) this.HandleError(Error.TooManyCatches); SourceLocationBuilder slb = new SourceLocationBuilder(this.scanner.SourceLocationOfLastScannedToken); this.GetNextToken(); TypeExpression exeptionType; NameDeclaration/*?*/ name = null; if (this.currentToken == Token.LeftParenthesis) { this.Skip(Token.LeftParenthesis); exeptionType = this.ParseTypeExpression(false, false, followers|Token.Identifier|Token.RightParenthesis); if (Parser.IdentifierOrNonReservedKeyword[this.currentToken]) name = this.ParseNameDeclaration(); this.Skip(Token.RightParenthesis); } else { exeptionType = this.GetTypeExpressionFor(Token.Object, slb.GetSourceLocation()); } BlockStatement body = this.ParseBlock(followers); slb.UpdateToSpan(body.SourceLocation); CatchClause result = new CatchClause(exeptionType, null, name, body, slb); //^ assume followers[this.currentToken] || this.currentToken == Token.EndOfFile; return result; }
private void ParseConstructor(List<ITypeDeclarationMember> members, List<SourceCustomAttribute>/*?*/ attributes, List<ModifierToken> modifiers, SourceLocationBuilder sctx, TokenSet followers) //^ requires Parser.IdentifierOrNonReservedKeyword[this.currentToken]; //^ 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); this.LookForModifier(modifiers, Token.New, Error.InvalidModifier); this.LookForModifier(modifiers, Token.Extern, Error.InvalidModifier); this.LookForModifier(modifiers, Token.Override, Error.InvalidModifier); this.LookForModifier(modifiers, Token.Readonly, Error.InvalidModifier); this.LookForModifier(modifiers, Token.Sealed, Error.InvalidModifier); this.LookForModifier(modifiers, Token.Static, Error.InvalidModifier); 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 name = new NameDeclaration(this.nameTable.Ctor, this.scanner.SourceLocationOfLastScannedToken); //^ assume this.currentToken != Token.EndOfFile; //follows from the precondition this.GetNextToken(); List<Ast.ParameterDeclaration> parameters = new List<Ast.ParameterDeclaration>(); List<Statement> statements = new List<Statement>(); SourceLocationBuilder bodyCtx = new SourceLocationBuilder(this.scanner.SourceLocationOfLastScannedToken); BlockStatement body = new BlockStatement(statements, bodyCtx); MethodDeclaration constructor = new MethodDeclaration(attributes, flags, visibility, new NamedTypeExpression(this.RootQualifiedNameFor(Token.Void)), null, name, null, parameters, null, body, sctx); members.Add(constructor); this.ParseParameters(parameters, Token.RightParenthesis, followers|Token.Where|Token.LeftBrace|Token.Semicolon|Token.Colon); SourceLocationBuilder callCtx = new SourceLocationBuilder(this.scanner.SourceLocationOfLastScannedToken); Token kind = Token.Base; IEnumerable<Expression> arguments = Expression.EmptyCollection; if (this.currentToken == Token.Colon) { this.GetNextToken(); callCtx = new SourceLocationBuilder(this.scanner.SourceLocationOfLastScannedToken); if (this.currentToken == Token.This) { kind = Token.This; this.GetNextToken(); if (this.currentToken == Token.LeftParenthesis) arguments = this.ParseArgumentList(callCtx, followers).AsReadOnly(); else { callCtx.UpdateToSpan(this.scanner.SourceLocationOfLastScannedToken); this.SkipTo(followers|Token.LeftBrace, Error.ExpectedLeftParenthesis); } } else if (this.currentToken == Token.Base) { this.GetNextToken(); if (this.currentToken == Token.LeftParenthesis) arguments = this.ParseArgumentList(callCtx, followers).AsReadOnly(); else { callCtx.UpdateToSpan(this.scanner.SourceLocationOfLastScannedToken); this.SkipTo(followers|Token.LeftBrace, Error.ExpectedLeftParenthesis); } } else { callCtx.UpdateToSpan(this.scanner.SourceLocationOfLastScannedToken); this.SkipTo(followers|Token.LeftBrace, Error.ThisOrBaseExpected); } } if (kind == Token.Base) { statements.Add(new FieldInitializerStatement()); statements.Add(new ExpressionStatement(new BaseClassConstructorCall(arguments, callCtx))); } else statements.Add(new ExpressionStatement(new ChainedConstructorCall(arguments, callCtx))); this.ParseBody(statements, bodyCtx, followers); //^ assert followers[this.currentToken] || this.currentToken == Token.EndOfFile; sctx.UpdateToSpan(bodyCtx.GetSourceLocation()); //^ assume followers[this.currentToken] || this.currentToken == Token.EndOfFile; }
private TypeExpression ParseTypeExpression(bool formsPartOfBooleanExpression, bool allowEmptyArguments, TokenSet followers) //^ ensures followers[this.currentToken] || this.currentToken == Token.EndOfFile; { if (this.currentToken == Token.EndOfFile) { this.HandleError(Error.TypeExpected); return this.GetTypeExpressionFor(Token.Object, SourceDummy.SourceLocation); } TokenSet followersOrTypeOperator = followers|Parser.TypeOperator; TypeExpression type = this.ParseBaseTypeExpression(allowEmptyArguments, followersOrTypeOperator); SourceLocationBuilder sctx = new SourceLocationBuilder(type.SourceLocation); for (; ; ) { sctx.UpdateToSpan(this.scanner.SourceLocationOfLastScannedToken); switch (this.currentToken) { case Token.BitwiseAnd: this.HandleError(Error.ExpectedIdentifier); //TODO: this matches C#, but a better error would be nice this.GetNextToken(); break; case Token.LeftBracket: uint rank = this.ParseRankSpecifier(sctx, followersOrTypeOperator); type = this.ParseArrayType(rank, type, sctx, followersOrTypeOperator); break; case Token.Multiply: { this.GetNextToken(); type = new PointerTypeExpression(type, sctx.GetSourceLocation()); break; } case Token.LogicalNot: { this.GetNextToken(); type = new NonNullTypeExpression(type, sctx.GetSourceLocation()); break; } case Token.Conditional: { if (formsPartOfBooleanExpression && Parser.NullableTypeNonFollower[this.PeekNextToken()]) goto done; this.GetNextToken(); type = new NullableTypeExpression(type, sctx.GetSourceLocation()); break; } default: goto done; } } done: this.SkipTo(followers); return type; }
private void ParseMethod(List<ITypeDeclarationMember> members, List<SourceCustomAttribute>/*?*/ attributes, List<ModifierToken> modifiers, TypeExpression type, List<TypeExpression>/*?*/ implementedInterfaces, NameDeclaration name, SourceLocationBuilder sctx, TokenSet followers) //^ ensures followers[this.currentToken] || this.currentToken == Token.EndOfFile; { MethodDeclaration.Flags flags = 0; TypeMemberVisibility visibility = this.ConvertToTypeMemberVisibility(modifiers); if (this.LookForModifier(modifiers, Token.Abstract, Error.None)) flags |= MethodDeclaration.Flags.Abstract; if (this.LookForModifier(modifiers, Token.New, Error.None)) flags |= MethodDeclaration.Flags.New; if (this.LookForModifier(modifiers, Token.Extern, Error.None)) flags |= MethodDeclaration.Flags.External; if (this.LookForModifier(modifiers, Token.Override, Error.None)) flags |= MethodDeclaration.Flags.Override; this.LookForModifier(modifiers, Token.Readonly, Error.InvalidModifier); if (this.LookForModifier(modifiers, Token.Sealed, Error.None)) flags |= MethodDeclaration.Flags.Sealed; if (this.LookForModifier(modifiers, Token.Static, Error.None)) flags |= MethodDeclaration.Flags.Static; if (this.LookForModifier(modifiers, Token.Unsafe, Error.None)) flags |= MethodDeclaration.Flags.Unsafe; if (this.LookForModifier(modifiers, Token.Virtual, Error.None)) flags |= MethodDeclaration.Flags.Virtual; this.LookForModifier(modifiers, Token.Volatile, Error.InvalidModifier); List<Ast.GenericMethodParameterDeclaration> genericParameters = new List<Ast.GenericMethodParameterDeclaration>(); List<Ast.ParameterDeclaration> parameters = new List<Ast.ParameterDeclaration>(); List<Statement> statements = new List<Statement>(); SourceLocationBuilder bodyCtx = new SourceLocationBuilder(this.scanner.SourceLocationOfLastScannedToken); BlockStatement body = new BlockStatement(statements, bodyCtx); bool isExtensionMethod; this.ParseGenericMethodParameters(genericParameters, followers|Token.LeftParenthesis|Token.Where|Token.LeftBrace|Token.Semicolon); this.ParseParameters(parameters, Token.RightParenthesis, followers|Token.Where|Token.LeftBrace|Token.Semicolon, out isExtensionMethod); if (isExtensionMethod) flags |= MethodDeclaration.Flags.ExtensionMethod; MethodDeclaration method = new MethodDeclaration(attributes, flags, visibility, type, implementedInterfaces, name, genericParameters, parameters, null, body, sctx); members.Add(method); // Now: how to get this.ParseGenericMethodParameterConstraintsClauses(genericParameters, followers|Token.LeftBrace|Token.Semicolon); //bool swallowedSemicolonAlready = false; //this.ParseMethodContract(oper, followers|Token.LeftBrace|Token.Semicolon, ref swallowedSemicolonAlready); this.ParseBody(statements, bodyCtx, followers); //^ assert followers[this.currentToken] || this.currentToken == Token.EndOfFile; sctx.UpdateToSpan(bodyCtx.GetSourceLocation()); //^ assume followers[this.currentToken] || this.currentToken == Token.EndOfFile; }
private Expression ParseNew(TokenSet followers) //^ requires this.currentToken == Token.New; //^ ensures followers[this.currentToken] || this.currentToken == Token.EndOfFile; { SourceLocationBuilder ctx = new SourceLocationBuilder(this.scanner.SourceLocationOfLastScannedToken); this.GetNextToken(); if (this.currentToken == Token.LeftBracket) return this.ParseNewImplicitlyTypedArray(ctx, followers); if (this.currentToken == Token.LeftBrace) return this.ParseNewAnonymousTypeInstance(ctx, followers); TypeExpression t = this.ParseBaseTypeExpression(false, followers|Parser.InfixOperators|Token.LeftBracket|Token.LeftParenthesis|Token.RightParenthesis); if (this.currentToken == Token.Conditional) { SourceLocationBuilder slb = new SourceLocationBuilder(t.SourceLocation); slb.UpdateToSpan(this.scanner.SourceLocationOfLastScannedToken); //^ assume this.currentToken == Token.Conditional; //no side effects from the methods can touch this.currentToken this.GetNextToken(); t = new NullableTypeExpression(t, slb); //} else if (this.currentToken == Token.LogicalNot) { // TypeExpression type = t; // t = new NonNullableTypeExpression(type); // t.SourceContext = type.SourceContext; // t.SourceContext.EndPos = this.scanner.endPos; // this.GetNextToken(); } else if (this.currentToken == Token.Multiply) { SourceLocationBuilder slb = new SourceLocationBuilder(t.SourceLocation); slb.UpdateToSpan(this.scanner.SourceLocationOfLastScannedToken); //^ assume this.currentToken == Token.Multiply; //no side effects from the methods can touch this.currentToken this.GetNextToken(); t = new PointerTypeExpression(t, slb); } ctx.UpdateToSpan(t.SourceLocation); TypeExpression et = t; uint rank = 0; while (this.currentToken == Token.LeftBracket) { Token nextTok = this.PeekNextToken(); if (nextTok != Token.Comma && nextTok != Token.RightBracket) break; //not a rank specifier, but a size specifier rank = this.ParseRankSpecifier(ctx, followers|Token.LeftBrace|Token.LeftBracket|Token.LeftParenthesis|Token.RightParenthesis); et = t; t = new ArrayTypeExpression(et, rank, ctx); } if (rank > 0) { //new T[] {...} or new T[,] {{..} {...}...}, etc where T can also be an array type List<Expression> initializers; if (this.currentToken == Token.LeftBrace) initializers = this.ParseArrayInitializers(rank, et, followers, false, ctx); else { initializers = new List<Expression>(0); if (Parser.UnaryStart[this.currentToken]) this.HandleError(Error.ExpectedLeftBrace); else this.HandleError(Error.MissingArraySize); while (Parser.UnaryStart[this.currentToken]) { this.ParseExpression(followers|Token.Comma|Token.RightBrace); if (this.currentToken != Token.Comma) break; this.GetNextToken(); } ctx.UpdateToSpan(this.scanner.SourceLocationOfLastScannedToken); this.SkipOverTo(Token.RightBrace, followers); } return new CreateArray(et, initializers.AsReadOnly(), new List<Expression>(0).AsReadOnly(), rank, new List<Expression>(0).AsReadOnly(), ctx); } if (this.currentToken == Token.LeftBracket) { //new T[x] or new T[x,y] etc. possibly followed by an initializer or element type rank specifier this.GetNextToken(); List<Expression> sizes = this.ParseExpressionList(ctx, followers|Token.LeftBrace|Token.LeftBracket); rank = (uint)sizes.Count; List<Expression> initializers; if (this.currentToken == Token.LeftBrace) initializers = this.ParseArrayInitializers(rank, t, followers, false, ctx); else { uint elementRank = 0; tryAgain: while (this.currentToken == Token.LeftBracket) { Token nextTok = this.PeekNextToken(); if (nextTok != Token.Comma && nextTok != Token.RightBracket) break; //not a rank specifier, but a size specifier elementRank = this.ParseRankSpecifier(ctx, followers|Token.LeftBrace|Token.LeftBracket|Token.LeftParenthesis|Token.RightParenthesis); t = new ArrayTypeExpression(t, elementRank, ctx); } if (this.currentToken == Token.LeftBrace) initializers = this.ParseArrayInitializers(rank, t, followers, false, ctx); else { if (this.currentToken == Token.LeftBracket) { //new T[x][y] or something like that this.GetNextToken(); this.HandleError(Error.InvalidArray); elementRank = (uint)this.ParseExpressionList(ctx, followers).Count; goto tryAgain; } else { initializers = new List<Expression>(0); ctx.UpdateToSpan(this.scanner.SourceLocationOfLastScannedToken); this.SkipTo(followers); } } } return new CreateArray(t, initializers.AsReadOnly(), new List<Expression>(0).AsReadOnly(), rank, sizes.AsReadOnly(), ctx); } //new T(...) IEnumerable<Expression> arguments = Expression.EmptyCollection; IEnumerable<Expression> elementValues = Expression.EmptyCollection; IEnumerable<NamedArgument> namedArguments = NamedArgument.EmptyCollection; if (this.currentToken == Token.LeftParenthesis) { //if (t is NonNullableTypeExpression) { // this.SkipTo(followers, Error.BadNewExpr); // return null; //} arguments = this.ParseArgumentList(ctx, followers|Token.LeftBrace).AsReadOnly(); } else if (this.currentToken != Token.LeftBrace) { this.SkipTo(followers, Error.BadNewExpr); } Expression result = new CreateObjectInstance(t, arguments, ctx.GetSourceLocation()); if (this.currentToken == Token.LeftBrace) { this.ParseElementValuesOrNamedArguments(ref elementValues, ref namedArguments, ctx, followers); if (elementValues != Expression.EmptyCollection) return new PopulateCollection(result, elementValues, ctx); else if (namedArguments != NamedArgument.EmptyCollection) return new InitializeObject(result, namedArguments, ctx); else { this.HandleError(Error.SyntaxError); //TODO: better error } } return result; }
protected override Expression ParseBraceLabeledExpression(SourceLocationBuilder slb, TokenSet followers) { var lab = (VccLabeledExpression)this.ParseLabeledExpression(followers | Token.RightBrace); this.Skip(Token.RightBrace); var body = this.ParseExpression(followers); var labString = lab.Label.Name.Value; var labName = new VccByteStringLiteral(labString, lab.Label.SourceLocation); var labArg = lab.Expression; if (labArg is DummyExpression) labArg = new CompileTimeConstant(1, false, lab.Label.SourceLocation); if (labString == "use") { // this condition is sort of a hack, it should likely look at some function \lbl_use(...) or something labArg = new VccByteStringLiteral(labArg.SourceLocation.Source, labArg.SourceLocation); } var args = new[] { labName, labArg, body }; slb.UpdateToSpan(body.SourceLocation); return new VccMethodCall(this.GetSimpleNameFor("\\labeled_expression"), args, slb.GetSourceLocation()); }