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 QualifiedName RootQualifiedNameFor(Token tok, ISourceLocation sctx) //^ requires tok == Token.Bool || tok == Token.Decimal || tok == Token.Sbyte || //^ tok == Token.Byte || tok == Token.Short || tok == Token.Ushort || //^ tok == Token.Int || tok == Token.Uint || tok == Token.Long || //^ tok == Token.Ulong || tok == Token.Char || tok == Token.Float || //^ tok == Token.Double || tok == Token.Object || tok == Token.String || //^ tok == Token.Void; { RootNamespaceExpression rootNs = new RootNamespaceExpression(sctx); AliasQualifiedName systemNs = new AliasQualifiedName(rootNs, this.GetSimpleNameFor("System"), sctx); switch (tok) { case Token.Bool: return new QualifiedName(systemNs, this.GetSimpleNameFor("Boolean"), sctx); case Token.Decimal: return new QualifiedName(systemNs, this.GetSimpleNameFor("Decimal"), sctx); case Token.Sbyte: return new QualifiedName(systemNs, this.GetSimpleNameFor("SByte"), sctx); case Token.Byte: return new QualifiedName(systemNs, this.GetSimpleNameFor("Byte"), sctx); case Token.Short: return new QualifiedName(systemNs, this.GetSimpleNameFor("Int16"), sctx); case Token.Ushort: return new QualifiedName(systemNs, this.GetSimpleNameFor("UInt16"), sctx); case Token.Int: return new QualifiedName(systemNs, this.GetSimpleNameFor("Int32"), sctx); case Token.Uint: return new QualifiedName(systemNs, this.GetSimpleNameFor("UInt32"), sctx); case Token.Long: return new QualifiedName(systemNs, this.GetSimpleNameFor("Int64"), sctx); case Token.Ulong: return new QualifiedName(systemNs, this.GetSimpleNameFor("UInt64"), sctx); case Token.Char: return new QualifiedName(systemNs, this.GetSimpleNameFor("Char"), sctx); case Token.Float: return new QualifiedName(systemNs, this.GetSimpleNameFor("Single"), sctx); case Token.Double: return new QualifiedName(systemNs, this.GetSimpleNameFor("Double"), sctx); case Token.Object: return new QualifiedName(systemNs, this.GetSimpleNameFor("Object"), sctx); case Token.String: return new QualifiedName(systemNs, this.GetSimpleNameFor("String"), sctx); default: //^ assert tok == Token.Void; return new QualifiedName(systemNs, this.GetSimpleNameFor("Void"), sctx); } }
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; }