private BlockStatement ParseStatementBlock(TokenSet followers) { SourceLocationBuilder slb = new SourceLocationBuilder(this.scanner.CurrentSourceLocation); List<Statement> statements = new List<Statement>(); this.ParseStatements(statements, followers); slb.UpdateToSpan(this.scanner.CurrentSourceLocation); return new BlockStatement(statements, slb); }
private Statement ParseDo(TokenSet followers) //^ requires this.currentToken == Token.Do; //^ ensures followers[this.currentToken] || this.currentToken == Token.EndOfFile; { SourceLocationBuilder slb = new SourceLocationBuilder(this.scanner.CurrentSourceLocation); this.GetNextToken(); this.Skip(Token.While); Expression condition = this.ParseExpression(followers|Token.EndOfLine); this.Skip(Token.EndOfLine); BlockStatement body = this.ParseStatementBlock(followers|Token.Loop); slb.UpdateToSpan(this.scanner.CurrentSourceLocation); WhileDoStatement result = new WhileDoStatement(condition, body, slb); this.SkipClosingKeyword(Token.Loop, followers); return result; }
protected override List<Expression> ParseArgumentList(SourceLocationBuilder slb, TokenSet followers) { var result = new List<Expression>(); this.Skip(Token.LeftParenthesis); while (this.currentToken != Token.RightParenthesis) { if (this.currentToken == Token.Specification) { result.Add(this.ParseSpecArgument(followers | Token.Comma | Token.Specification | Token.RightParenthesis)); continue; } result.Add(this.ParseArgumentExpression(followers | Token.Comma | Token.Specification | Token.RightParenthesis)); if (this.currentToken == Token.Comma) { this.GetNextToken(); continue; } if (this.currentToken == Token.Specification) continue; break; } slb.UpdateToSpan(this.scanner.SourceLocationOfLastScannedToken); this.SkipOverTo(Token.RightParenthesis, followers); return result; }
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 void ParseNestedDelegateDeclaration(List<ITypeDeclarationMember> typeMembers, List<SourceCustomAttribute>/*?*/ attributes, TypeDeclaration.Flags flags, SourceLocationBuilder sctx, TokenSet followers) //^ requires this.currentToken == Token.Delegate; //^ ensures followers[this.currentToken] || this.currentToken == Token.EndOfFile; { this.GetNextToken(); TypeExpression returnType = this.ParseTypeExpression(false, false, followers|Token.LeftParenthesis|Token.Semicolon|Parser.IdentifierOrNonReservedKeyword); if (!Parser.IdentifierOrNonReservedKeyword[this.currentToken]) this.HandleError(Error.ExpectedIdentifier); NameDeclaration name = this.ParseNameDeclaration(); List<Ast.GenericTypeParameterDeclaration> genericParameters = new List<Ast.GenericTypeParameterDeclaration>(); List<Ast.ParameterDeclaration> parameters = new List<Ast.ParameterDeclaration>(); SignatureDeclaration signature = new SignatureDeclaration(returnType, parameters, sctx); NestedDelegateDeclaration type = new NestedDelegateDeclaration(attributes, flags, name, genericParameters, signature, sctx); typeMembers.Add(type); this.ParseGenericTypeParameters(genericParameters, followers|Token.LeftParenthesis|Token.Where|Token.Semicolon); this.ParseParameters(parameters, Token.RightParenthesis, followers|Token.Where|Token.Semicolon, sctx); this.ParseGenericTypeParameterConstraintsClauses(genericParameters, followers|Token.Semicolon); sctx.UpdateToSpan(this.scanner.SourceLocationOfLastScannedToken); if (this.currentToken == Token.Semicolon) this.GetNextToken(); this.SkipTo(followers); }
private CompileTimeConstant ParseRealLiteral() //^ requires this.currentToken == Token.RealLiteral; { string tokStr = this.scanner.GetTokenSource(); SourceLocationBuilder ctx = new SourceLocationBuilder(this.scanner.SourceLocationOfLastScannedToken); TypeCode tc = this.scanner.ScanNumberSuffix(); ctx.UpdateToSpan(this.scanner.SourceLocationOfLastScannedToken); CompileTimeConstant result; string/*?*/ typeName = null; switch (tc) { case TypeCode.Single: typeName = "float"; float fVal; if (!Single.TryParse(tokStr, System.Globalization.NumberStyles.Float, System.Globalization.CultureInfo.InvariantCulture, out fVal)) this.HandleError(ctx, Error.FloatOverflow, typeName); else if (fVal == 0f && tokStr.IndexOfAny(nonZeroDigits) >= 0) this.HandleError(ctx, Error.FloatOverflow, typeName); result = new CompileTimeConstant(fVal, false, ctx); break; case TypeCode.Empty: case TypeCode.Double: typeName = "double"; double dVal; if (!Double.TryParse(tokStr, System.Globalization.NumberStyles.Float, System.Globalization.CultureInfo.InvariantCulture, out dVal)) this.HandleError(ctx, Error.FloatOverflow, typeName); else if (dVal == 0d && tokStr.IndexOfAny(nonZeroDigits) >= 0) this.HandleError(ctx, Error.FloatOverflow, typeName); result = new CompileTimeConstant(dVal, tc == TypeCode.Empty, ctx); break; case TypeCode.Decimal: typeName = "decimal"; decimal decVal; if (!Decimal.TryParse(tokStr, System.Globalization.NumberStyles.Float, System.Globalization.CultureInfo.InvariantCulture, out decVal)) this.HandleError(ctx, Error.FloatOverflow, typeName); result = new CompileTimeConstant(decVal, false, ctx); break; default: this.HandleError(Error.ExpectedSemicolon); goto case TypeCode.Empty; } //^ assume this.currentToken == Token.RealLiteral; //follows from the precondition this.GetNextToken(); return result; }
private CompileTimeConstant ParseHexLiteral() //^ requires this.currentToken == Token.HexLiteral; { string tokStr = this.scanner.GetTokenSource(); //^ assume tokStr.StartsWith("0x") || tokStr.StartsWith("0X"); //The scanner should not return a Token.HexLiteral when this is not the case. SourceLocationBuilder ctx = new SourceLocationBuilder(this.scanner.SourceLocationOfLastScannedToken); TypeCode tc = this.scanner.ScanNumberSuffix(); ctx.UpdateToSpan(this.scanner.SourceLocationOfLastScannedToken); CompileTimeConstant result; switch (tc) { case TypeCode.Single: case TypeCode.Double: case TypeCode.Decimal: this.HandleError(Error.ExpectedSemicolon); goto default; default: ulong ul; //^ assume tokStr.Length >= 2; if (!UInt64.TryParse(tokStr.Substring(2), System.Globalization.NumberStyles.HexNumber, System.Globalization.CultureInfo.InvariantCulture, out ul)) { this.HandleError(ctx, Error.IntOverflow); ul = 0; } result = GetConstantOfSmallestIntegerTypeThatIncludes(ul, tc, ctx); break; } //^ assume this.currentToken == Token.HexLiteral; //follows from the precondition this.GetNextToken(); return result; }
private Indexer ParseIndexer(Expression indexedObject, TokenSet followers) //^ requires this.currentToken == Token.LeftBracket; //^ ensures followers[this.currentToken] || this.currentToken == Token.EndOfFile; { SourceLocationBuilder slb = new SourceLocationBuilder(indexedObject.SourceLocation); this.GetNextToken(); List<Expression> indices = new List<Expression>(); while (this.currentToken != Token.RightBracket) { Expression index = this.ParseExpression(followers|Token.Comma|Token.RightBracket); indices.Add(index); if (this.currentToken != Token.Comma) break; this.GetNextToken(); } indices.TrimExcess(); slb.UpdateToSpan(this.scanner.SourceLocationOfLastScannedToken); Indexer result = new Indexer(indexedObject, indices.AsReadOnly(), slb); this.SkipOverTo(Token.RightBracket, followers); return result; }
private List<Expression> ParseArgumentList(SourceLocationBuilder slb, TokenSet followers) //^ requires this.currentToken == Token.LeftParenthesis; //^ ensures followers[this.currentToken] || this.currentToken == Token.EndOfFile; { this.GetNextToken(); TokenSet followersOrCommaOrRightParenthesis = followers|Token.Comma|Token.RightParenthesis; List<Expression> arguments = new List<Expression>(); if (this.currentToken != Token.RightParenthesis) { Expression argument = this.ParseArgument(followersOrCommaOrRightParenthesis); arguments.Add(argument); while (this.currentToken == Token.Comma) { this.GetNextToken(); argument = this.ParseArgument(followersOrCommaOrRightParenthesis); arguments.Add(argument); } } arguments.TrimExcess(); slb.UpdateToSpan(this.scanner.SourceLocationOfLastScannedToken); this.SkipOverTo(Token.RightParenthesis, followers); return arguments; }
private uint ParseRankSpecifier(SourceLocationBuilder sctx, TokenSet followers) //^ requires this.currentToken == Token.LeftBracket; //^ ensures result > 0; //^ ensures followers[this.currentToken] || this.currentToken == Token.EndOfFile; { this.GetNextToken(); uint rank = 1; while (this.currentToken == Token.Comma) { rank++; this.GetNextToken(); } ISourceLocation tokLoc = this.scanner.SourceLocationOfLastScannedToken; //^ assume tokLoc.SourceDocument == sctx.SourceDocument; sctx.UpdateToSpan(tokLoc); this.SkipOverTo(Token.RightBracket, followers); return rank; }
private Expression ParseGetValueOfTypedReference(TokenSet followers) //^ requires this.currentToken == Token.RefValue; //^ ensures followers[this.currentToken] || this.currentToken == Token.EndOfFile; { SourceLocationBuilder slb = new SourceLocationBuilder(this.scanner.SourceLocationOfLastScannedToken); this.GetNextToken(); this.Skip(Token.LeftParenthesis); Expression e = this.ParseExpression(followers|Token.Comma); this.Skip(Token.Comma); TypeExpression te = this.ParseTypeExpression(false, false, followers|Token.RightParenthesis); slb.UpdateToSpan(this.scanner.SourceLocationOfLastScannedToken); Expression result = new GetValueOfTypedReference(e, te, slb); this.SkipOverTo(Token.RightParenthesis, followers); return result; }
private LambdaParameter ParseLambdaParameter(bool allowType, TokenSet followers) //^ ensures followers[this.currentToken] || this.currentToken == Token.EndOfFile; { SourceLocationBuilder slb = new SourceLocationBuilder(this.scanner.SourceLocationOfLastScannedToken); bool isOut = false; bool isRef = false; Token firstToken = this.currentToken; NameDeclaration parameterName = new NameDeclaration(this.GetNameFor(this.scanner.GetIdentifierString()), this.scanner.SourceLocationOfLastScannedToken); TypeExpression/*?*/ parameterType = null; if (allowType) { if (this.currentToken == Token.Out) { isOut = true; this.GetNextToken(); } else if (this.currentToken == Token.Ref) { isRef = true; this.GetNextToken(); } parameterType = this.ParseTypeExpression(false, false, followers); if ((this.currentToken == Token.Comma || this.currentToken == Token.RightParenthesis) && Parser.IdentifierOrNonReservedKeyword[firstToken]) { parameterType = null; } else { parameterName = new NameDeclaration(this.GetNameFor(this.scanner.GetIdentifierString()), this.scanner.SourceLocationOfLastScannedToken); } } slb.UpdateToSpan(this.scanner.SourceLocationOfLastScannedToken); LambdaParameter result = new LambdaParameter(isOut, isRef, parameterType, parameterName, slb); if (!Parser.IdentifierOrNonReservedKeyword[this.currentToken]) this.HandleError(Error.ExpectedIdentifier); else { //^ assume this.currentToken != Token.EndOfFile; //follows from definition of Parser.IdentifierOrNonReservedKeyword this.GetNextToken(); } this.SkipTo(followers); return result; }
private Expression ParsePrimaryExpression(TokenSet followers) //^ ensures followers[this.currentToken] || this.currentToken == Token.EndOfFile; { ISourceLocation sctx = this.scanner.SourceLocationOfLastScannedToken; Expression expression = new DummyExpression(sctx); switch (this.currentToken) { case Token.ArgList: this.GetNextToken(); expression = new RuntimeArgumentHandleExpression(sctx); break; case Token.Delegate: expression = this.ParseAnonymousMethod(followers); break; case Token.New: expression = this.ParseNew(followers|Token.Dot|Token.LeftBracket|Token.Arrow); break; case Token.Identifier: expression = this.ParseSimpleName(followers|Token.Dot|Token.DoubleColon|Token.Lambda|Token.LeftParenthesis); if (this.currentToken == Token.DoubleColon) { if (((SimpleName)expression).Name == this.nameTable.global) expression = new RootNamespaceExpression(expression.SourceLocation); expression = this.ParseQualifiedName(expression, followers|Token.Dot|Token.LessThan|Token.LeftParenthesis|Token.AddOne|Token.SubtractOne); } else if (this.currentToken == Token.Lambda) { expression = this.ParseLambda((SimpleName)expression, followers); } break; case Token.Null: expression = new NullLiteral(sctx); this.GetNextToken(); break; case Token.True: expression = new CompileTimeConstant(true, false, sctx); this.GetNextToken(); break; case Token.False: expression = new CompileTimeConstant(false, false, sctx); this.GetNextToken(); break; case Token.CharLiteral: expression = new CompileTimeConstant(this.scanner.charLiteralValue, false, sctx); this.GetNextToken(); break; case Token.HexLiteral: expression = this.ParseHexLiteral(); break; case Token.IntegerLiteral: expression = this.ParseIntegerLiteral(); break; case Token.RealLiteral: expression = this.ParseRealLiteral(); break; case Token.StringLiteral: expression = new CompileTimeConstant(this.scanner.GetString(), false, sctx); this.GetNextToken(); break; case Token.This: expression = new ThisReference(sctx); this.GetNextToken(); break; case Token.Base: expression = new BaseClassReference(sctx); this.GetNextToken(); break; case Token.Typeof: case Token.Sizeof: case Token.Default: expression = this.ParseTypeofSizeofOrDefault(followers); break; case Token.Stackalloc: return this.ParseStackalloc(followers); case Token.Checked: case Token.MakeRef: case Token.RefType: case Token.Unchecked: expression = this.ParseCheckedOrMakeRefOrRefTypeOrUnchecked(followers); break; case Token.RefValue: expression = this.ParseGetValueOfTypedReference(followers); 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: expression = this.RootQualifiedNameFor(this.currentToken, sctx); this.GetNextToken(); break; case Token.LeftParenthesis: expression = this.ParseCastExpression(followers|Token.Dot|Token.LeftBracket|Token.Arrow); break; default: if (Parser.IdentifierOrNonReservedKeyword[this.currentToken]) goto case Token.Identifier; if (Parser.InfixOperators[this.currentToken]) { this.HandleError(Error.InvalidExprTerm, this.scanner.GetTokenSource()); //^ assume this.currentToken != Token.EndOfFile; //should not be a member of InfixOperators this.GetNextToken(); } else this.SkipTo(followers|Parser.PrimaryStart, Error.InvalidExprTerm, this.scanner.GetTokenSource()); if (Parser.PrimaryStart[this.currentToken]) return this.ParsePrimaryExpression(followers); goto done; } expression = this.ParseIndexerCallOrSelector(expression, followers|Token.AddOne|Token.SubtractOne); for (; ; ) { switch (this.currentToken) { case Token.AddOne: SourceLocationBuilder slb = new SourceLocationBuilder(expression.SourceLocation); slb.UpdateToSpan(this.scanner.SourceLocationOfLastScannedToken); this.GetNextToken(); expression = new PostfixIncrement(new TargetExpression(expression), slb); break; case Token.SubtractOne: slb = new SourceLocationBuilder(expression.SourceLocation); slb.UpdateToSpan(this.scanner.SourceLocationOfLastScannedToken); this.GetNextToken(); expression = new PostfixDecrement(new TargetExpression(expression), slb); break; case Token.Arrow: case Token.Dot: case Token.LeftBracket: expression = this.ParseIndexerCallOrSelector(expression, followers|Token.AddOne|Token.SubtractOne); break; default: goto done; } } done: this.SkipTo(followers); return expression; }
private Expression ParseUnaryExpression(TokenSet followers) //^ ensures followers[this.currentToken] || this.currentToken == Token.EndOfFile; { switch (this.currentToken) { case Token.AddOne: case Token.BitwiseAnd: case Token.BitwiseNot: case Token.LogicalNot: case Token.Multiply: case Token.Plus: case Token.Subtract: case Token.SubtractOne: SourceLocationBuilder slb = new SourceLocationBuilder(this.scanner.SourceLocationOfLastScannedToken); Token operatorToken = this.currentToken; this.GetNextToken(); Expression operand = this.ParseUnaryExpression(followers); slb.UpdateToSpan(operand.SourceLocation); Expression result = AllocateUnaryExpression(operatorToken, operand, slb); //^ assume followers[this.currentToken] || this.currentToken == Token.EndOfFile; return result; //case Token.LeftParenthesis: // return this.ParseCastExpression(followers); default: return this.ParsePrimaryExpression(followers); } }
private Expression ParseConditional(Expression condition, TokenSet followers) //^ requires this.currentToken == Token.Conditional; //^ ensures followers[this.currentToken] || this.currentToken == Token.EndOfFile; { this.GetNextToken(); SourceLocationBuilder slb = new SourceLocationBuilder(condition.SourceLocation); Expression resultIfTrue = this.ParseExpression(followers|Token.Colon); Expression resultIfFalse; if (this.currentToken == Token.Colon) { this.GetNextToken(); resultIfFalse = this.ParseExpression(followers); } else { this.Skip(Token.Colon); //gives appropriate error message if (!followers[this.currentToken]) //Assume that only the : is missing. Go ahead as if it were specified. resultIfFalse = this.ParseExpression(followers); else resultIfFalse = this.ParseDummyExpression(); } slb.UpdateToSpan(resultIfFalse.SourceLocation); Expression result = new Conditional(condition, resultIfTrue, resultIfFalse, slb); this.SkipTo(followers); return result; }
private Expression ParseQualifiedName(Expression qualifier, TokenSet followers) //^ requires this.currentToken == Token.Arrow || this.currentToken == Token.Dot || this.currentToken == Token.DoubleColon; //^ requires this.currentToken == Token.DoubleColon ==> qualifier is SimpleName || qualifier is RootNamespaceExpression; //^ ensures followers[this.currentToken] || this.currentToken == Token.EndOfFile; { Token tok = this.currentToken; SourceLocationBuilder slb = new SourceLocationBuilder(qualifier.SourceLocation); this.GetNextToken(); SimpleName name = this.ParseSimpleName(followers); slb.UpdateToSpan(name.SourceLocation); Expression result; if (tok == Token.Arrow) result = new PointerQualifiedName(qualifier, name, slb); else if (tok == Token.DoubleColon) result = new AliasQualifiedName(qualifier, name, slb); else { //^ assert tok == Token.Dot; result = new QualifiedName(qualifier, name, slb); } //^ assume followers[this.currentToken] || this.currentToken == Token.EndOfFile; return result; }
private Expression ParseTypeofSizeofOrDefault(TokenSet followers) //^ requires this.currentToken == Token.Typeof || this.currentToken == Token.Sizeof || this.currentToken == Token.Default; //^ ensures followers[this.currentToken] || this.currentToken == Token.EndOfFile; { Token tok = this.currentToken; SourceLocationBuilder slb = new SourceLocationBuilder(this.scanner.SourceLocationOfLastScannedToken); this.GetNextToken(); this.Skip(Token.LeftParenthesis); TypeExpression type = this.ParseTypeExpression(false, true, followers|Token.RightParenthesis); slb.UpdateToSpan(this.scanner.SourceLocationOfLastScannedToken); this.SkipOverTo(Token.RightParenthesis, followers); Expression result; if (tok == Token.Typeof) result = new TypeOf(type, slb); else if (tok == Token.Sizeof) result = new SizeOf(type, slb); else { //^ assert tok == Token.Default; result = new DefaultValue(type, slb); } //^ assume followers[this.currentToken] || this.currentToken == Token.EndOfFile; return result; }
private Expression ParseStackalloc(TokenSet followers) //^ requires this.currentToken == Token.Stackalloc; //^ ensures followers[this.currentToken] || this.currentToken == Token.EndOfFile; { SourceLocationBuilder slb = new SourceLocationBuilder(this.scanner.SourceLocationOfLastScannedToken); this.GetNextToken(); TypeExpression elementType = this.ParseBaseTypeExpression(false, followers|Token.LeftBracket); Token openingDelimiter = this.currentToken; if (this.currentToken != Token.LeftBracket) { this.HandleError(Error.BadStackAllocExpr); if (this.currentToken == Token.LeftParenthesis) this.GetNextToken(); } else this.GetNextToken(); Expression size = this.ParseExpression(followers|Token.RightBracket|Token.RightParenthesis); slb.UpdateToSpan(this.scanner.SourceLocationOfLastScannedToken); if (this.currentToken == Token.RightParenthesis && openingDelimiter == Token.LeftParenthesis) this.GetNextToken(); else this.Skip(Token.RightBracket); Expression result = new CreateStackArray(elementType, size, slb); this.SkipTo(followers); return result; }
private Expression ParseArgument(TokenSet followers) //^ ensures followers[this.currentToken] || this.currentToken == Token.EndOfFile; { switch (this.currentToken) { case Token.Ref: SourceLocationBuilder slb = new SourceLocationBuilder(this.scanner.SourceLocationOfLastScannedToken); this.GetNextToken(); Expression expr = this.ParseExpression(followers); slb.UpdateToSpan(expr.SourceLocation); Expression refArg = new RefArgument(new AddressableExpression(expr), slb); //^ assume followers[this.currentToken] || this.currentToken == Token.EndOfFile; return refArg; case Token.Out: slb = new SourceLocationBuilder(this.scanner.SourceLocationOfLastScannedToken); this.GetNextToken(); expr = this.ParseExpression(followers); slb.UpdateToSpan(expr.SourceLocation); Expression outArg = new OutArgument(new TargetExpression(expr), slb); //^ assume followers[this.currentToken] || this.currentToken == Token.EndOfFile; return outArg; //case Token.ArgList: // slb = new SourceLocationBuilder(this.scanner.CurrentSourceContext); // this.GetNextToken(); // if (this.currentToken == Token.LeftParenthesis) { // ExpressionList el = this.ParseExpressionList(followers, ref sctx); // return new ArglistArgumentExpression(el, sctx); // } // return new ArglistExpression(sctx); default: return this.ParseExpression(followers); } }
private Expression ParseAnonymousMethod(TokenSet followers) //^ requires this.currentToken == Token.Delegate; //^ ensures followers[this.currentToken] || this.currentToken == Token.EndOfFile; { SourceLocationBuilder slb = new SourceLocationBuilder(this.scanner.SourceLocationOfLastScannedToken); this.GetNextToken(); List<Ast.ParameterDeclaration> parameters = new List<Ast.ParameterDeclaration>(); if (this.currentToken == Token.LeftParenthesis) this.ParseParameters(parameters, Token.RightParenthesis, followers); BlockStatement body = this.ParseBody(followers); //TODO: just parse a block //^ assert followers[this.currentToken] || this.currentToken == Token.EndOfFile; slb.UpdateToSpan(body.SourceLocation); Expression result = new AnonymousMethod(parameters, body, slb); //^ assume followers[this.currentToken] || this.currentToken == Token.EndOfFile; return result; }
private Expression ParseParenthesizedExpression(bool keepParentheses, TokenSet followers) //^ ensures followers[this.currentToken] || this.currentToken == Token.EndOfFile; { SourceLocationBuilder sctx = new SourceLocationBuilder(this.scanner.SourceLocationOfLastScannedToken); if (this.currentToken == Token.LeftBrace) { Expression dummy = new DummyExpression(sctx); this.SkipTo(followers, Error.SyntaxError, "("); return dummy; } this.Skip(Token.LeftParenthesis); Expression result = this.ParseExpression(followers|Token.RightParenthesis|Token.Colon); if (keepParentheses) { sctx.UpdateToSpan(this.scanner.SourceLocationOfLastScannedToken); result = new Parenthesis(result, sctx); } this.SkipOverTo(Token.RightParenthesis, followers); return result; }
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; }
private CompileTimeConstant ParseIntegerLiteral() //^ requires this.currentToken == Token.IntegerLiteral; { string tokStr = this.scanner.GetTokenSource(); SourceLocationBuilder ctx = new SourceLocationBuilder(this.scanner.SourceLocationOfLastScannedToken); TypeCode tc = this.scanner.ScanNumberSuffix(); ctx.UpdateToSpan(this.scanner.SourceLocationOfLastScannedToken); CompileTimeConstant result; switch (tc) { case TypeCode.Single: float f; if (!Single.TryParse(tokStr, System.Globalization.NumberStyles.None, System.Globalization.CultureInfo.InvariantCulture, out f)) { this.HandleError(ctx, Error.FloatOverflow); f = float.NaN; } result = new CompileTimeConstant(f, false, ctx); break; case TypeCode.Double: double d; if (!Double.TryParse(tokStr, System.Globalization.NumberStyles.None, System.Globalization.CultureInfo.InvariantCulture, out d)) { this.HandleError(ctx, Error.FloatOverflow); d = double.NaN; } result = new CompileTimeConstant(d, false, ctx); break; case TypeCode.Decimal: decimal m; if (!decimal.TryParse(tokStr, System.Globalization.NumberStyles.None, System.Globalization.CultureInfo.InvariantCulture, out m)) { this.HandleError(ctx, Error.IntOverflow); m = decimal.Zero; } result = new CompileTimeConstant(m, false, ctx); break; default: ulong ul; if (!UInt64.TryParse(tokStr, System.Globalization.NumberStyles.None, System.Globalization.CultureInfo.InvariantCulture, out ul)) { this.HandleError(ctx, Error.IntOverflow); ul = 0; } result = GetConstantOfSmallestIntegerTypeThatIncludes(ul, tc, ctx); break; } //^ assume this.currentToken == Token.IntegerLiteral; //follows from the precondition this.GetNextToken(); return result; }
private Expression ParseNewAnonymousTypeInstance(SourceLocationBuilder slb, TokenSet followers) //^ requires this.currentToken == Token.LeftBrace; //^ ensures followers[this.currentToken] || this.currentToken == Token.EndOfFile; { this.GetNextToken(); TokenSet followersOrCommaOrRightBrace = followers|Token.Comma|Token.RightBrace; List<Expression> initializers = new List<Expression>(); while (Parser.UnaryStart[this.currentToken]) // ^ invariant forall{IExpression initializer in initializers; initializer is NamedArgument || initializer is SimpleName || initializer is QualifiedName}; { SourceLocationBuilder eslb = new SourceLocationBuilder(this.scanner.SourceLocationOfLastScannedToken); Expression e = this.ParseUnaryExpression(followersOrCommaOrRightBrace|Parser.InfixOperators); SimpleName/*?*/ id = e as SimpleName; if (this.currentToken == Token.Assign) { this.GetNextToken(); if (id == null) this.HandleError(e.SourceLocation, Error.ExpectedIdentifier); e = this.ParseExpression(followersOrCommaOrRightBrace); eslb.UpdateToSpan(e.SourceLocation); if (id != null) initializers.Add(new NamedArgument(id, e, eslb)); } else { if (id != null) initializers.Add(id); else { QualifiedName/*?*/ qualId = e as QualifiedName; if (qualId != null) initializers.Add(qualId); else { this.HandleError(e.SourceLocation, Error.SyntaxError); } } } if (this.currentToken != Token.Comma) break; this.GetNextToken(); } slb.UpdateToSpan(this.scanner.SourceLocationOfLastScannedToken); Expression result = new CreateAnonymousObject(initializers, slb); this.SkipOverTo(Token.RightBracket, followers); return result; }
private void ParseNestedNamespaceDeclaration(List<INamespaceDeclarationMember> parentMembers, TokenSet followers) //^ requires this.currentToken == Token.Namespace; //^ ensures followers[this.currentToken] || this.currentToken == Token.EndOfFile; { SourceLocationBuilder nsCtx = new SourceLocationBuilder(this.scanner.SourceLocationOfLastScannedToken); this.GetNextToken(); if (!Parser.IdentifierOrNonReservedKeyword[this.currentToken]) this.HandleError(Error.ExpectedIdentifier); NameDeclaration nsName = this.ParseNameDeclaration(); nsCtx.UpdateToSpan(this.scanner.SourceLocationOfLastScannedToken); List<INamespaceDeclarationMember> nestedMembers = new List<INamespaceDeclarationMember>(); List<Ast.SourceCustomAttribute> nestedSourceAttributes = new List<Ast.SourceCustomAttribute>(); NestedNamespaceDeclaration nestedNamespace = new NestedNamespaceDeclaration(nsName, nestedMembers, nestedSourceAttributes, nsCtx); parentMembers.Add(nestedNamespace); while (this.currentToken == Token.Dot) { this.GetNextToken(); if (!Parser.IdentifierOrNonReservedKeyword[this.currentToken]) this.HandleError(Error.ExpectedIdentifier); nsName = this.ParseNameDeclaration(); parentMembers = nestedMembers; nestedMembers = new List<INamespaceDeclarationMember>(); nestedSourceAttributes = new List<SourceCustomAttribute>(); nestedNamespace = new NestedNamespaceDeclaration(nsName, nestedMembers, nestedSourceAttributes, nsCtx); parentMembers.Add(nestedNamespace); } this.Skip(Token.LeftBrace); this.ParseNamespaceBody(nestedMembers, null, followers|Token.RightBrace); nsCtx.UpdateToSpan(this.scanner.SourceLocationOfLastScannedToken); this.SkipOverTo(Token.RightBrace, followers); }
private List<Expression> ParseExpressionList(SourceLocationBuilder slb, TokenSet followers) //^ ensures followers[this.currentToken] || this.currentToken == Token.EndOfFile; { TokenSet followersOrCommaOrRightBracket = followers|Token.Comma|Token.RightBracket; List<Expression> result = new List<Expression>(); if (this.currentToken != Token.RightBracket) { Expression expression = this.ParseExpression(followersOrCommaOrRightBracket); result.Add(expression); while (this.currentToken == Token.Comma) { this.GetNextToken(); expression = this.ParseExpression(followersOrCommaOrRightBracket); result.Add(expression); } } slb.UpdateToSpan(this.scanner.SourceLocationOfLastScannedToken); this.Skip(Token.RightBracket); this.SkipTo(followers); return result; }
private void ParseRestOfTypeDeclaration(SourceLocationBuilder sctx, TypeDeclaration type, List<Ast.GenericTypeParameterDeclaration> genericParameters, List<TypeExpression> baseTypes, List<ITypeDeclarationMember> members, TokenSet followers) //^ ensures followers[this.currentToken] || this.currentToken == Token.EndOfFile; { this.ParseGenericTypeParameters(genericParameters, followers|Token.Colon|Token.LeftBrace|Token.Where); this.ParseBaseTypes(baseTypes, followers|Token.LeftBrace|Token.Where); this.ParseGenericTypeParameterConstraintsClauses(genericParameters, followers|Token.LeftBrace); this.Skip(Token.LeftBrace); this.ParseTypeMembers(sctx, type.Name, members, followers|Token.RightBrace); ISourceLocation tokLoc = this.scanner.SourceLocationOfLastScannedToken; //^ assume tokLoc.SourceDocument == sctx.SourceDocument; sctx.UpdateToSpan(tokLoc); this.Skip(Token.RightBrace); if (this.currentToken == Token.Semicolon) this.GetNextToken(); this.SkipTo(followers); }
private List<Expression> ParseArrayInitializers(uint rank, TypeExpression elementType, TokenSet followers, bool doNotSkipClosingBrace, SourceLocationBuilder ctx) //^ requires this.currentToken == Token.LeftBrace; //^ ensures followers[this.currentToken] || this.currentToken == Token.EndOfFile; { this.GetNextToken(); List<Expression> initialValues = new List<Expression>(); if (this.currentToken == Token.RightBrace) { ctx.UpdateToSpan(this.scanner.SourceLocationOfLastScannedToken); this.GetNextToken(); initialValues.TrimExcess(); return initialValues; } while (true) { if (rank > 1) { List<Expression> elemArrayInitializers; SourceLocationBuilder ectx = new SourceLocationBuilder(this.scanner.SourceLocationOfLastScannedToken); if (this.currentToken == Token.LeftBrace) { elemArrayInitializers = this.ParseArrayInitializers(rank-1, elementType, followers|Token.Comma|Token.LeftBrace, false, ectx); } else { elemArrayInitializers = new List<Expression>(0); this.SkipTo(followers|Token.Comma|Token.LeftBrace, Error.ExpectedLeftBrace); } CreateArray elemArr = new CreateArray(elementType, elemArrayInitializers.AsReadOnly(), new List<Expression>(0).AsReadOnly(), rank-1, new List<Expression>(0).AsReadOnly(), ectx); initialValues.Add(elemArr); } else { if (this.currentToken == Token.LeftBrace) { this.HandleError(Error.ArrayInitInBadPlace); SourceLocationBuilder ectx = new SourceLocationBuilder(this.scanner.SourceLocationOfLastScannedToken); //^ assume this.currentToken == Token.LeftBrace; List<Expression> elemArrayInitializers = this.ParseArrayInitializers(1, elementType, followers|Token.Comma|Token.LeftBrace, false, ectx); CreateArray elemArr = new CreateArray(elementType, elemArrayInitializers.AsReadOnly(), new List<Expression>(0).AsReadOnly(), 1, new List<Expression>(0).AsReadOnly(), ectx); initialValues.Add(elemArr); } else initialValues.Add(this.ParseExpression(followers|Token.Comma|Token.RightBrace)); } if (this.currentToken != Token.Comma) break; this.GetNextToken(); if (this.currentToken == Token.RightBrace) break; } ctx.UpdateToSpan(this.scanner.SourceLocationOfLastScannedToken); if (!doNotSkipClosingBrace) { this.Skip(Token.RightBrace); this.SkipTo(followers); } initialValues.TrimExcess(); return initialValues; }
private void ParseTypeMembers(SourceLocationBuilder sctx, IName typeName, List<ITypeDeclarationMember> members, TokenSet followers) //^ ensures followers[this.currentToken] || this.currentToken == Token.EndOfFile; { TokenSet followersOrTypeMemberStart = followers|Parser.TypeMemberStart; for (; ; ) { SourceLocationBuilder tctx = new SourceLocationBuilder(this.scanner.SourceLocationOfLastScannedToken); List<SourceCustomAttribute>/*?*/ attributes = this.ParseAttributes(followersOrTypeMemberStart); List<ModifierToken> modifiers = this.ParseModifiers(); switch (this.currentToken) { case Token.Class: this.ParseNestedClassDeclaration(members, attributes, this.ConvertToTypeDeclarationFlags(modifiers), tctx, followersOrTypeMemberStart); break; case Token.Interface: this.ParseNestedInterfaceDeclaration(members, attributes, this.ConvertToTypeDeclarationFlags(modifiers), tctx, followersOrTypeMemberStart); break; case Token.Struct: this.ParseNestedStructDeclaration(members, attributes, this.ConvertToTypeDeclarationFlags(modifiers), tctx, followersOrTypeMemberStart); break; case Token.Enum: this.ParseNestedEnumDeclaration(members, attributes, this.ConvertToTypeDeclarationFlags(modifiers), tctx, followersOrTypeMemberStart); break; case Token.Delegate: this.ParseNestedDelegateDeclaration(members, attributes, this.ConvertToTypeDeclarationFlags(modifiers), tctx, followersOrTypeMemberStart); break; case Token.Const: this.ParseConst(members, attributes, modifiers, tctx, followersOrTypeMemberStart); break; case Token.Invariant: goto default; //this.ParseInvariant(attributes, modifierTokens, modifierContexts, tctx, 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: this.ParseConstructorOrFieldOrMethodOrPropertyOrStaticInitializer(typeName, members, attributes, modifiers, tctx, followersOrTypeMemberStart); break; case Token.Event: this.ParseEvent(members, attributes, modifiers, tctx, followersOrTypeMemberStart); break; case Token.Operator: case Token.Explicit: case Token.Implicit: this.ParseOperator(members, attributes, modifiers, null, tctx, followersOrTypeMemberStart); break; case Token.BitwiseNot: this.ParseDestructor(typeName, members, attributes, modifiers, tctx, followersOrTypeMemberStart); break; default: if (Parser.IdentifierOrNonReservedKeyword[this.currentToken]) goto case Token.Identifier; sctx.UpdateToSpan(this.scanner.SourceLocationOfLastScannedToken); this.SkipTo(followers); return; } } }
private Expression ParseCastExpression(TokenSet followers) //^ requires this.currentToken == Token.LeftParenthesis; //^ ensures followers[this.currentToken] || this.currentToken == Token.EndOfFile; { SourceLocationBuilder slb = new SourceLocationBuilder(this.scanner.SourceLocationOfLastScannedToken); int position = this.scanner.CurrentDocumentPosition(); this.GetNextToken(); List<IErrorMessage> savedErrors = this.scannerAndParserErrors; this.scannerAndParserErrors = new List<IErrorMessage>(0); TypeExpression targetType = this.ParseTypeExpression(false, false, followers|Token.RightParenthesis); bool isCast = false; bool isLambda = false; if (this.currentToken == Token.RightParenthesis && this.scannerAndParserErrors.Count == 0) { if (targetType is NamedTypeExpression) { Token nextTok = this.PeekNextToken(); isCast = Parser.CastFollower[nextTok]; isLambda = nextTok == Token.Lambda; } else //Parsed a type expression that cannot also be a value expression. isCast = true; } this.scannerAndParserErrors = savedErrors; Expression expression; if (!isCast) { //Encountered an error while trying to parse (type expr) and there is some reason to be believe that this might not be a type argument list at all. //Back up the scanner and let the caller carry on as if it knew that < is the less than operator this.scanner.RestoreDocumentPosition(position); this.currentToken = Token.None; this.GetNextToken(); if (isLambda) expression = this.ParseLambda(followers); else expression = this.ParseParenthesizedExpression(true, followers); } else { this.Skip(Token.RightParenthesis); Expression valueToCast = this.ParseUnaryExpression(followers); slb.UpdateToSpan(valueToCast.SourceLocation); expression = new Cast(valueToCast, targetType, slb); } for (; ; ) { switch (this.currentToken) { case Token.Arrow: case Token.Dot: case Token.LeftBracket: expression = this.ParseIndexerCallOrSelector(expression, followers); break; default: goto done; } } done: this.SkipTo(followers); return expression; }