#define DEBUG using System; using System.Collections.Generic; using System.Diagnostics; using Microsoft.VisualBasic.CompilerServices; namespace AspClassic.Parser; /// /// A parser for the Visual Basic .NET language based on the grammar /// documented in the Language Specification. /// public sealed class Parser : IDisposable { private enum PrecedenceLevel { None, Xor, Or, And, Not, Relational, Shift, Concatenate, Plus, Modulus, IntegralDivide, Multiply, Negate, Power, Range } private sealed class ExternalSourceContext { public Location Start; public string File; public long Line; } private sealed class RegionContext { public Location Start; public string Description; } private sealed class ConditionalCompilationContext { public bool BlockActive; public bool AnyBlocksActive; public bool SeenElse; } private Scanner Scanner; private IList ErrorTable; private IList ExternalLineMappings; private IList SourceRegions; private IList ExternalChecksums; private IDictionary ConditionalCompilationConstants; private bool ErrorInConstruct; private bool AtBeginningOfLine; private bool Preprocess; private bool CanContinueWithoutLineTerminator; private Stack BlockContextStack; private ExternalSourceContext CurrentExternalSourceContext; private Stack RegionContextStack; private Stack ConditionalCompilationContextStack; private bool Disposed; public Parser() { BlockContextStack = new Stack(); RegionContextStack = new Stack(); ConditionalCompilationContextStack = new Stack(); Disposed = false; } /// /// Disposes the parser. /// public void Dispose() { if (!Disposed) { Disposed = true; Scanner.Close(); } } void IDisposable.Dispose() { //ILSpy generated this explicit interface implementation from .override directive in Dispose this.Dispose(); } private Token Peek() { return Scanner.Peek(); } private Token PeekAheadOne() { Token Start = Read(); Token NextToken = Peek(); Backtrack(Start); return NextToken; } private TokenType PeekAheadFor(params TokenType[] tokens) { Token Start = Peek(); Token Current = Start; while (!CanEndStatement(Current)) { foreach (TokenType Token in tokens) { if (Current.AsUnreservedKeyword() == Token) { Backtrack(Start); return Token; } } Current = Read(); } Backtrack(Start); return TokenType.None; } private Token Read() { return Scanner.Read(); } private Location ReadLocation() { return Read().Span.Start; } private void Backtrack(Token token) { Scanner.Seek(token); } private void ResyncAt(params TokenType[] tokenTypes) { Token CurrentToken = Peek(); while (CurrentToken.Type != TokenType.Colon && CurrentToken.Type != TokenType.EndOfStream && CurrentToken.Type != TokenType.LineTerminator && !BeginsStatement(CurrentToken)) { foreach (TokenType TokenType in tokenTypes) { if (CurrentToken.Type == TokenType) { return; } } Read(); CurrentToken = Peek(); } } private List ParseTrailingComments() { List Comments = new List(); while (Peek().Type == TokenType.Comment) { CommentToken CommentToken = (CommentToken)Scanner.Read(); Comments.Add(new Comment(CommentToken.Comment, CommentToken.IsREM, CommentToken.Span)); } if (Comments.Count > 0) { return Comments; } return null; } private void PushBlockContext(TreeType type) { BlockContextStack.Push(type); } private void PopBlockContext() { BlockContextStack.Pop(); } private TreeType CurrentBlockContextType() { if (BlockContextStack.Count == 0) { return TreeType.SyntaxError; } return BlockContextStack.Peek(); } private static OperatorType GetBinaryOperator(TokenType type, bool allowRange = false) { switch (type) { case TokenType.Ampersand: return OperatorType.Concatenate; case TokenType.Star: return OperatorType.Multiply; case TokenType.ForwardSlash: return OperatorType.Divide; case TokenType.BackwardSlash: return OperatorType.IntegralDivide; case TokenType.Caret: return OperatorType.Power; case TokenType.Plus: return OperatorType.Plus; case TokenType.Minus: return OperatorType.Minus; case TokenType.LessThan: return OperatorType.LessThan; case TokenType.LessThanEquals: return OperatorType.LessThanEquals; case TokenType.Equals: return OperatorType.Equals; case TokenType.NotEquals: return OperatorType.NotEquals; case TokenType.GreaterThan: return OperatorType.GreaterThan; case TokenType.GreaterThanEquals: return OperatorType.GreaterThanEquals; case TokenType.LessThanLessThan: return OperatorType.ShiftLeft; case TokenType.GreaterThanGreaterThan: return OperatorType.ShiftRight; case TokenType.Mod: return OperatorType.Modulus; case TokenType.Or: return OperatorType.Or; case TokenType.OrElse: return OperatorType.OrElse; case TokenType.And: return OperatorType.And; case TokenType.AndAlso: return OperatorType.AndAlso; case TokenType.Xor: return OperatorType.Xor; case TokenType.Like: return OperatorType.Like; case TokenType.Is: return OperatorType.Is; case TokenType.IsNot: return OperatorType.IsNot; case TokenType.To: if (allowRange) { return OperatorType.To; } return OperatorType.None; default: return OperatorType.None; } } private static PrecedenceLevel GetOperatorPrecedence(OperatorType @operator) { switch (@operator) { case OperatorType.To: return PrecedenceLevel.Range; case OperatorType.Power: return PrecedenceLevel.Power; case OperatorType.UnaryPlus: case OperatorType.Negate: return PrecedenceLevel.Negate; case OperatorType.Multiply: case OperatorType.Divide: return PrecedenceLevel.Multiply; case OperatorType.IntegralDivide: return PrecedenceLevel.IntegralDivide; case OperatorType.Modulus: return PrecedenceLevel.Modulus; case OperatorType.Plus: case OperatorType.Minus: return PrecedenceLevel.Plus; case OperatorType.Concatenate: return PrecedenceLevel.Concatenate; case OperatorType.ShiftLeft: case OperatorType.ShiftRight: return PrecedenceLevel.Shift; case OperatorType.Like: case OperatorType.Is: case OperatorType.IsNot: case OperatorType.Equals: case OperatorType.NotEquals: case OperatorType.LessThan: case OperatorType.LessThanEquals: case OperatorType.GreaterThan: case OperatorType.GreaterThanEquals: return PrecedenceLevel.Relational; case OperatorType.Not: return PrecedenceLevel.Not; case OperatorType.And: case OperatorType.AndAlso: return PrecedenceLevel.And; case OperatorType.Or: case OperatorType.OrElse: return PrecedenceLevel.Or; case OperatorType.Xor: return PrecedenceLevel.Xor; default: return PrecedenceLevel.None; } } private static OperatorType GetCompoundAssignmentOperatorType(TokenType tokenType) { return tokenType switch { TokenType.PlusEquals => OperatorType.Plus, TokenType.AmpersandEquals => OperatorType.Concatenate, TokenType.StarEquals => OperatorType.Multiply, TokenType.MinusEquals => OperatorType.Minus, TokenType.ForwardSlashEquals => OperatorType.Divide, TokenType.BackwardSlashEquals => OperatorType.IntegralDivide, TokenType.CaretEquals => OperatorType.Power, TokenType.LessThanLessThanEquals => OperatorType.ShiftLeft, TokenType.GreaterThanGreaterThanEquals => OperatorType.ShiftRight, _ => OperatorType.None, }; } private static TreeType GetAssignmentOperator(TokenType tokenType) { switch (tokenType) { case TokenType.Equals: return TreeType.AssignmentStatement; case TokenType.AmpersandEquals: case TokenType.StarEquals: case TokenType.PlusEquals: case TokenType.MinusEquals: case TokenType.ForwardSlashEquals: case TokenType.BackwardSlashEquals: case TokenType.CaretEquals: case TokenType.LessThanLessThanEquals: case TokenType.GreaterThanGreaterThanEquals: return TreeType.CompoundAssignmentStatement; default: return TreeType.SyntaxError; } } private static bool IsRelationalOperator(TokenType type) { return type >= TokenType.LessThan && type <= TokenType.GreaterThanEquals; } private static bool IsOverloadableOperator(Token op) { switch (op.Type) { case TokenType.And: case TokenType.CType: case TokenType.Like: case TokenType.Mod: case TokenType.Not: case TokenType.Or: case TokenType.Xor: case TokenType.Ampersand: case TokenType.Star: case TokenType.Plus: case TokenType.Minus: case TokenType.ForwardSlash: case TokenType.BackwardSlash: case TokenType.Caret: case TokenType.LessThan: case TokenType.LessThanEquals: case TokenType.Equals: case TokenType.NotEquals: case TokenType.GreaterThan: case TokenType.GreaterThanEquals: case TokenType.LessThanLessThan: case TokenType.GreaterThanGreaterThan: return true; case TokenType.Identifier: if (op.AsUnreservedKeyword() == TokenType.IsTrue || op.AsUnreservedKeyword() == TokenType.IsFalse) { return true; } break; } return false; } private static BlockType GetContinueType(TokenType tokenType) { return tokenType switch { TokenType.Do => BlockType.Do, TokenType.For => BlockType.For, TokenType.While => BlockType.While, _ => BlockType.None, }; } private static BlockType GetExitType(TokenType tokenType) { return tokenType switch { TokenType.Do => BlockType.Do, TokenType.For => BlockType.For, TokenType.While => BlockType.While, TokenType.Select => BlockType.Select, TokenType.Sub => BlockType.Sub, TokenType.Function => BlockType.Function, TokenType.Property => BlockType.Property, TokenType.Try => BlockType.Try, _ => BlockType.None, }; } private static BlockType GetBlockType(TokenType type) { return type switch { TokenType.While => BlockType.While, TokenType.Select => BlockType.Select, TokenType.If => BlockType.If, TokenType.Try => BlockType.Try, TokenType.SyncLock => BlockType.SyncLock, TokenType.Using => BlockType.Using, TokenType.With => BlockType.With, TokenType.Sub => BlockType.Sub, TokenType.Function => BlockType.Function, TokenType.Operator => BlockType.Operator, TokenType.Get => BlockType.Get, TokenType.Set => BlockType.Set, TokenType.Event => BlockType.Event, TokenType.AddHandler => BlockType.AddHandler, TokenType.RemoveHandler => BlockType.RemoveHandler, TokenType.RaiseEvent => BlockType.RaiseEvent, TokenType.Property => BlockType.Property, TokenType.Class => BlockType.Class, TokenType.Structure => BlockType.Structure, TokenType.Module => BlockType.Module, TokenType.Interface => BlockType.Interface, TokenType.Enum => BlockType.Enum, TokenType.Namespace => BlockType.Namespace, _ => BlockType.None, }; } private void ReportSyntaxError(SyntaxError syntaxError) { if (!ErrorInConstruct) { ErrorInConstruct = true; if (ErrorTable != null) { ErrorTable.Add(syntaxError); } } } private void ReportSyntaxError(SyntaxErrorType errorType, Span span) { ReportSyntaxError(new SyntaxError(errorType, span)); } private void ReportSyntaxError(SyntaxErrorType errorType, Token firstToken, Token lastToken) { if (firstToken.Type == TokenType.LexicalError) { ReportSyntaxError(((ErrorToken)firstToken).SyntaxError); } else { ReportSyntaxError(errorType, SpanFrom(firstToken, lastToken)); } } private void ReportSyntaxError(SyntaxErrorType errorType, Token token) { ReportSyntaxError(errorType, token, token); } private static bool StatementEndsBlock(TreeType blockStatementType, Statement endStatement) { switch (blockStatementType) { case TreeType.DoBlockStatement: return endStatement.Type == TreeType.LoopStatement; case TreeType.ForBlockStatement: case TreeType.ForEachBlockStatement: return endStatement.Type == TreeType.NextStatement; case TreeType.WhileBlockStatement: return endStatement.Type == TreeType.EndBlockStatement && ((EndBlockStatement)endStatement).EndType == BlockType.While; case TreeType.SyncLockBlockStatement: return endStatement.Type == TreeType.EndBlockStatement && ((EndBlockStatement)endStatement).EndType == BlockType.SyncLock; case TreeType.UsingBlockStatement: return endStatement.Type == TreeType.EndBlockStatement && ((EndBlockStatement)endStatement).EndType == BlockType.Using; case TreeType.WithBlockStatement: return endStatement.Type == TreeType.EndBlockStatement && ((EndBlockStatement)endStatement).EndType == BlockType.With; case TreeType.TryBlockStatement: case TreeType.CatchBlockStatement: return endStatement.Type == TreeType.CatchStatement || endStatement.Type == TreeType.FinallyStatement || (endStatement.Type == TreeType.EndBlockStatement && ((EndBlockStatement)endStatement).EndType == BlockType.Try); case TreeType.FinallyBlockStatement: return endStatement.Type == TreeType.EndBlockStatement && ((EndBlockStatement)endStatement).EndType == BlockType.Try; case TreeType.SelectBlockStatement: case TreeType.CaseBlockStatement: return endStatement.Type == TreeType.CaseStatement || endStatement.Type == TreeType.CaseElseStatement || (endStatement.Type == TreeType.EndBlockStatement && ((EndBlockStatement)endStatement).EndType == BlockType.Select); case TreeType.CaseElseBlockStatement: return endStatement.Type == TreeType.EndBlockStatement && ((EndBlockStatement)endStatement).EndType == BlockType.Select; case TreeType.IfBlockStatement: case TreeType.ElseIfBlockStatement: return endStatement.Type == TreeType.ElseIfStatement || endStatement.Type == TreeType.ElseStatement || (endStatement.Type == TreeType.EndBlockStatement && ((EndBlockStatement)endStatement).EndType == BlockType.If); case TreeType.ElseBlockStatement: return endStatement.Type == TreeType.EndBlockStatement && ((EndBlockStatement)endStatement).EndType == BlockType.If; case TreeType.LineIfBlockStatement: return endStatement.Type == TreeType.EndBlockStatement && ((EndBlockStatement)endStatement).EndType == BlockType.If; case TreeType.SubDeclaration: case TreeType.ConstructorDeclaration: return endStatement.Type == TreeType.EndBlockStatement && ((EndBlockStatement)endStatement).EndType == BlockType.Sub; case TreeType.FunctionDeclaration: return endStatement.Type == TreeType.EndBlockStatement && ((EndBlockStatement)endStatement).EndType == BlockType.Function; case TreeType.OperatorDeclaration: return endStatement.Type == TreeType.EndBlockStatement && ((EndBlockStatement)endStatement).EndType == BlockType.Operator; case TreeType.GetAccessorDeclaration: return endStatement.Type == TreeType.EndBlockStatement && ((EndBlockStatement)endStatement).EndType == BlockType.Get; case TreeType.SetAccessorDeclaration: return endStatement.Type == TreeType.EndBlockStatement && ((EndBlockStatement)endStatement).EndType == BlockType.Set; case TreeType.PropertyDeclaration: return endStatement.Type == TreeType.EndBlockStatement && ((EndBlockStatement)endStatement).EndType == BlockType.Property; case TreeType.CustomEventDeclaration: return endStatement.Type == TreeType.EndBlockStatement && ((EndBlockStatement)endStatement).EndType == BlockType.Event; case TreeType.AddHandlerAccessorDeclaration: return endStatement.Type == TreeType.EndBlockStatement && ((EndBlockStatement)endStatement).EndType == BlockType.AddHandler; case TreeType.RemoveHandlerAccessorDeclaration: return endStatement.Type == TreeType.EndBlockStatement && ((EndBlockStatement)endStatement).EndType == BlockType.RemoveHandler; case TreeType.RaiseEventAccessorDeclaration: return endStatement.Type == TreeType.EndBlockStatement && ((EndBlockStatement)endStatement).EndType == BlockType.RaiseEvent; case TreeType.ClassDeclaration: return endStatement.Type == TreeType.EndBlockStatement && ((EndBlockStatement)endStatement).EndType == BlockType.Class; case TreeType.StructureDeclaration: return endStatement.Type == TreeType.EndBlockStatement && ((EndBlockStatement)endStatement).EndType == BlockType.Structure; case TreeType.ModuleDeclaration: return endStatement.Type == TreeType.EndBlockStatement && ((EndBlockStatement)endStatement).EndType == BlockType.Module; case TreeType.InterfaceDeclaration: return endStatement.Type == TreeType.EndBlockStatement && ((EndBlockStatement)endStatement).EndType == BlockType.Interface; case TreeType.EnumDeclaration: return endStatement.Type == TreeType.EndBlockStatement && ((EndBlockStatement)endStatement).EndType == BlockType.Enum; case TreeType.NamespaceDeclaration: return endStatement.Type == TreeType.EndBlockStatement && ((EndBlockStatement)endStatement).EndType == BlockType.Namespace; default: Debug.Assert(condition: false, "Unexpected."); return false; } } private static bool DeclarationEndsBlock(TreeType blockDeclarationType, EndBlockDeclaration endDeclaration) { switch (blockDeclarationType) { case TreeType.SubDeclaration: case TreeType.ConstructorDeclaration: return endDeclaration.EndType == BlockType.Sub; case TreeType.FunctionDeclaration: return endDeclaration.EndType == BlockType.Function; case TreeType.OperatorDeclaration: return endDeclaration.EndType == BlockType.Operator; case TreeType.PropertyDeclaration: return endDeclaration.EndType == BlockType.Property; case TreeType.GetAccessorDeclaration: return endDeclaration.EndType == BlockType.Get; case TreeType.SetAccessorDeclaration: return endDeclaration.EndType == BlockType.Set; case TreeType.CustomEventDeclaration: return endDeclaration.EndType == BlockType.Event; case TreeType.AddHandlerAccessorDeclaration: return endDeclaration.EndType == BlockType.AddHandler; case TreeType.RemoveHandlerAccessorDeclaration: return endDeclaration.EndType == BlockType.RemoveHandler; case TreeType.RaiseEventAccessorDeclaration: return endDeclaration.EndType == BlockType.RaiseEvent; case TreeType.ClassDeclaration: return endDeclaration.EndType == BlockType.Class; case TreeType.StructureDeclaration: return endDeclaration.EndType == BlockType.Structure; case TreeType.ModuleDeclaration: return endDeclaration.EndType == BlockType.Module; case TreeType.InterfaceDeclaration: return endDeclaration.EndType == BlockType.Interface; case TreeType.EnumDeclaration: return endDeclaration.EndType == BlockType.Enum; case TreeType.NamespaceDeclaration: return endDeclaration.EndType == BlockType.Namespace; default: Debug.Assert(condition: false, "Unexpected."); return false; } } private static bool ValidInContext(TreeType blockType, TreeType declarationType) { switch (declarationType) { case TreeType.ImportsDeclaration: case TreeType.OptionDeclaration: case TreeType.AttributeDeclaration: return blockType == TreeType.File; case TreeType.NamespaceDeclaration: return blockType == TreeType.NamespaceDeclaration || blockType == TreeType.File; case TreeType.ClassDeclaration: case TreeType.StructureDeclaration: case TreeType.InterfaceDeclaration: case TreeType.EnumDeclaration: case TreeType.DelegateSubDeclaration: case TreeType.DelegateFunctionDeclaration: return blockType == TreeType.ClassDeclaration || blockType == TreeType.StructureDeclaration || blockType == TreeType.ModuleDeclaration || blockType == TreeType.InterfaceDeclaration || blockType == TreeType.NamespaceDeclaration || blockType == TreeType.File; case TreeType.ModuleDeclaration: return blockType == TreeType.NamespaceDeclaration || blockType == TreeType.File; case TreeType.SubDeclaration: case TreeType.FunctionDeclaration: case TreeType.PropertyDeclaration: case TreeType.EventDeclaration: return blockType == TreeType.ClassDeclaration || blockType == TreeType.StructureDeclaration || blockType == TreeType.ModuleDeclaration || blockType == TreeType.InterfaceDeclaration; case TreeType.CustomEventDeclaration: return blockType == TreeType.ClassDeclaration || blockType == TreeType.StructureDeclaration || blockType == TreeType.ModuleDeclaration; case TreeType.AddHandlerAccessorDeclaration: case TreeType.RemoveHandlerAccessorDeclaration: case TreeType.RaiseEventAccessorDeclaration: return blockType == TreeType.CustomEventDeclaration; case TreeType.OperatorDeclaration: return blockType == TreeType.ClassDeclaration || blockType == TreeType.StructureDeclaration; case TreeType.VariableListDeclaration: case TreeType.ExternalSubDeclaration: case TreeType.ExternalFunctionDeclaration: return blockType == TreeType.ClassDeclaration || blockType == TreeType.StructureDeclaration || blockType == TreeType.ModuleDeclaration; case TreeType.ConstructorDeclaration: return blockType == TreeType.ClassDeclaration || blockType == TreeType.StructureDeclaration; case TreeType.GetAccessorDeclaration: case TreeType.SetAccessorDeclaration: return blockType == TreeType.PropertyDeclaration; case TreeType.InheritsDeclaration: return blockType == TreeType.ClassDeclaration || blockType == TreeType.InterfaceDeclaration; case TreeType.ImplementsDeclaration: return blockType == TreeType.ClassDeclaration || blockType == TreeType.StructureDeclaration; case TreeType.EnumValueDeclaration: return blockType == TreeType.EnumDeclaration; case TreeType.EmptyDeclaration: return true; default: { Debug.Assert(condition: false, "Unexpected."); bool ValidInContext = default(bool); return ValidInContext; } } } private static SyntaxErrorType ValidDeclaration(TreeType blockType, Declaration declaration, List declarations) { if (!ValidInContext(blockType, declaration.Type)) { return InvalidDeclarationTypeError(blockType); } if (declaration.Type == TreeType.InheritsDeclaration) { foreach (Declaration ExistingDeclaration in declarations) { if (blockType == TreeType.ClassDeclaration || ExistingDeclaration.Type != TreeType.InheritsDeclaration) { return SyntaxErrorType.InheritsMustBeFirst; } } if (((InheritsDeclaration)declaration).InheritedTypes.Count > 1 && blockType != TreeType.InterfaceDeclaration) { return SyntaxErrorType.NoMultipleInheritance; } } if (declaration.Type == TreeType.ImplementsDeclaration) { foreach (Declaration ExistingDeclaration5 in declarations) { if (ExistingDeclaration5.Type != TreeType.InheritsDeclaration && ExistingDeclaration5.Type != TreeType.ImplementsDeclaration) { return SyntaxErrorType.ImplementsInWrongOrder; } } } if (declaration.Type == TreeType.OptionDeclaration) { foreach (Declaration ExistingDeclaration4 in declarations) { if (ExistingDeclaration4.Type != TreeType.OptionDeclaration) { return SyntaxErrorType.OptionStatementWrongOrder; } } } if (declaration.Type == TreeType.ImportsDeclaration) { foreach (Declaration ExistingDeclaration3 in declarations) { if (ExistingDeclaration3.Type != TreeType.OptionDeclaration && ExistingDeclaration3.Type != TreeType.ImportsDeclaration) { return SyntaxErrorType.ImportsStatementWrongOrder; } } } if (declaration.Type == TreeType.AttributeDeclaration) { foreach (Declaration ExistingDeclaration2 in declarations) { if (ExistingDeclaration2.Type != TreeType.OptionDeclaration && ExistingDeclaration2.Type != TreeType.ImportsDeclaration && ExistingDeclaration2.Type != TreeType.AttributeDeclaration) { return SyntaxErrorType.AttributesStatementWrongOrder; } } } return SyntaxErrorType.None; } private void ReportMismatchedEndError(TreeType blockType, Span actualEndSpan) { SyntaxErrorType ErrorType = default(SyntaxErrorType); switch (blockType) { case TreeType.DoBlockStatement: ErrorType = SyntaxErrorType.ExpectedLoop; break; case TreeType.ForBlockStatement: case TreeType.ForEachBlockStatement: ErrorType = SyntaxErrorType.ExpectedNext; break; case TreeType.WhileBlockStatement: ErrorType = SyntaxErrorType.ExpectedEndWhile; break; case TreeType.SelectBlockStatement: case TreeType.CaseBlockStatement: case TreeType.CaseElseBlockStatement: ErrorType = SyntaxErrorType.ExpectedEndSelect; break; case TreeType.SyncLockBlockStatement: ErrorType = SyntaxErrorType.ExpectedEndSyncLock; break; case TreeType.UsingBlockStatement: ErrorType = SyntaxErrorType.ExpectedEndUsing; break; case TreeType.IfBlockStatement: case TreeType.ElseIfBlockStatement: case TreeType.ElseBlockStatement: ErrorType = SyntaxErrorType.ExpectedEndIf; break; case TreeType.TryBlockStatement: case TreeType.CatchBlockStatement: case TreeType.FinallyBlockStatement: ErrorType = SyntaxErrorType.ExpectedEndTry; break; case TreeType.WithBlockStatement: ErrorType = SyntaxErrorType.ExpectedEndWith; break; case TreeType.SubDeclaration: case TreeType.ConstructorDeclaration: ErrorType = SyntaxErrorType.ExpectedEndSub; break; case TreeType.FunctionDeclaration: ErrorType = SyntaxErrorType.ExpectedEndFunction; break; case TreeType.OperatorDeclaration: ErrorType = SyntaxErrorType.ExpectedEndOperator; break; case TreeType.PropertyDeclaration: ErrorType = SyntaxErrorType.ExpectedEndProperty; break; case TreeType.GetAccessorDeclaration: ErrorType = SyntaxErrorType.ExpectedEndGet; break; case TreeType.SetAccessorDeclaration: ErrorType = SyntaxErrorType.ExpectedEndSet; break; case TreeType.CustomEventDeclaration: ErrorType = SyntaxErrorType.ExpectedEndEvent; break; case TreeType.AddHandlerAccessorDeclaration: ErrorType = SyntaxErrorType.ExpectedEndAddHandler; break; case TreeType.RemoveHandlerAccessorDeclaration: ErrorType = SyntaxErrorType.ExpectedEndRemoveHandler; break; case TreeType.RaiseEventAccessorDeclaration: ErrorType = SyntaxErrorType.ExpectedEndRaiseEvent; break; case TreeType.ClassDeclaration: ErrorType = SyntaxErrorType.ExpectedEndClass; break; case TreeType.StructureDeclaration: ErrorType = SyntaxErrorType.ExpectedEndStructure; break; case TreeType.ModuleDeclaration: ErrorType = SyntaxErrorType.ExpectedEndModule; break; case TreeType.InterfaceDeclaration: ErrorType = SyntaxErrorType.ExpectedEndInterface; break; case TreeType.EnumDeclaration: ErrorType = SyntaxErrorType.ExpectedEndEnum; break; case TreeType.NamespaceDeclaration: ErrorType = SyntaxErrorType.ExpectedEndNamespace; break; default: Debug.Assert(condition: false, "Unexpected."); break; } ReportSyntaxError(ErrorType, actualEndSpan); } private void ReportMissingBeginStatementError(TreeType blockStatementType, Statement endStatement) { SyntaxErrorType ErrorType = default(SyntaxErrorType); switch (endStatement.Type) { case TreeType.LoopStatement: ErrorType = SyntaxErrorType.LoopWithoutDo; break; case TreeType.NextStatement: ErrorType = SyntaxErrorType.NextWithoutFor; break; case TreeType.EndBlockStatement: switch (((EndBlockStatement)endStatement).EndType) { case BlockType.While: ErrorType = SyntaxErrorType.EndWhileWithoutWhile; break; case BlockType.Select: ErrorType = SyntaxErrorType.EndSelectWithoutSelect; break; case BlockType.SyncLock: ErrorType = SyntaxErrorType.EndSyncLockWithoutSyncLock; break; case BlockType.Using: ErrorType = SyntaxErrorType.EndUsingWithoutUsing; break; case BlockType.If: ErrorType = SyntaxErrorType.EndIfWithoutIf; break; case BlockType.Try: ErrorType = SyntaxErrorType.EndTryWithoutTry; break; case BlockType.With: ErrorType = SyntaxErrorType.EndWithWithoutWith; break; case BlockType.Sub: ErrorType = SyntaxErrorType.EndSubWithoutSub; break; case BlockType.Function: ErrorType = SyntaxErrorType.EndFunctionWithoutFunction; break; case BlockType.Operator: ErrorType = SyntaxErrorType.EndOperatorWithoutOperator; break; case BlockType.Get: ErrorType = SyntaxErrorType.EndGetWithoutGet; break; case BlockType.Set: ErrorType = SyntaxErrorType.EndSetWithoutSet; break; case BlockType.Property: ErrorType = SyntaxErrorType.EndPropertyWithoutProperty; break; case BlockType.Event: ErrorType = SyntaxErrorType.EndEventWithoutEvent; break; case BlockType.AddHandler: ErrorType = SyntaxErrorType.EndAddHandlerWithoutAddHandler; break; case BlockType.RemoveHandler: ErrorType = SyntaxErrorType.EndRemoveHandlerWithoutRemoveHandler; break; case BlockType.RaiseEvent: ErrorType = SyntaxErrorType.EndRaiseEventWithoutRaiseEvent; break; case BlockType.Class: ErrorType = SyntaxErrorType.EndClassWithoutClass; break; case BlockType.Structure: ErrorType = SyntaxErrorType.EndStructureWithoutStructure; break; case BlockType.Module: ErrorType = SyntaxErrorType.EndModuleWithoutModule; break; case BlockType.Interface: ErrorType = SyntaxErrorType.EndInterfaceWithoutInterface; break; case BlockType.Enum: ErrorType = SyntaxErrorType.EndEnumWithoutEnum; break; case BlockType.Namespace: ErrorType = SyntaxErrorType.EndNamespaceWithoutNamespace; break; default: Debug.Assert(condition: false, "Unexpected."); break; } break; case TreeType.CatchStatement: ErrorType = ((blockStatementType != TreeType.FinallyBlockStatement) ? SyntaxErrorType.CatchWithoutTry : SyntaxErrorType.CatchAfterFinally); break; case TreeType.FinallyStatement: ErrorType = ((blockStatementType != TreeType.FinallyBlockStatement) ? SyntaxErrorType.FinallyWithoutTry : SyntaxErrorType.FinallyAfterFinally); break; case TreeType.CaseStatement: ErrorType = ((blockStatementType != TreeType.CaseElseBlockStatement) ? SyntaxErrorType.CaseWithoutSelect : SyntaxErrorType.CaseAfterCaseElse); break; case TreeType.CaseElseStatement: ErrorType = ((blockStatementType != TreeType.CaseElseBlockStatement) ? SyntaxErrorType.CaseElseWithoutSelect : SyntaxErrorType.CaseElseAfterCaseElse); break; case TreeType.ElseIfStatement: ErrorType = ((blockStatementType != TreeType.ElseBlockStatement) ? SyntaxErrorType.ElseIfWithoutIf : SyntaxErrorType.ElseIfAfterElse); break; case TreeType.ElseStatement: ErrorType = ((blockStatementType != TreeType.ElseBlockStatement) ? SyntaxErrorType.ElseWithoutIf : SyntaxErrorType.ElseAfterElse); break; default: Debug.Assert(condition: false, "Unexpected."); break; } ReportSyntaxError(ErrorType, endStatement.Span); } private void ReportMissingBeginDeclarationError(EndBlockDeclaration endDeclaration) { SyntaxErrorType ErrorType = default(SyntaxErrorType); switch (endDeclaration.EndType) { case BlockType.Sub: ErrorType = SyntaxErrorType.EndSubWithoutSub; break; case BlockType.Function: ErrorType = SyntaxErrorType.EndFunctionWithoutFunction; break; case BlockType.Operator: ErrorType = SyntaxErrorType.EndOperatorWithoutOperator; break; case BlockType.Property: ErrorType = SyntaxErrorType.EndPropertyWithoutProperty; break; case BlockType.Get: ErrorType = SyntaxErrorType.EndGetWithoutGet; break; case BlockType.Set: ErrorType = SyntaxErrorType.EndSetWithoutSet; break; case BlockType.Event: ErrorType = SyntaxErrorType.EndEventWithoutEvent; break; case BlockType.AddHandler: ErrorType = SyntaxErrorType.EndAddHandlerWithoutAddHandler; break; case BlockType.RemoveHandler: ErrorType = SyntaxErrorType.EndRemoveHandlerWithoutRemoveHandler; break; case BlockType.RaiseEvent: ErrorType = SyntaxErrorType.EndRaiseEventWithoutRaiseEvent; break; case BlockType.Class: ErrorType = SyntaxErrorType.EndClassWithoutClass; break; case BlockType.Structure: ErrorType = SyntaxErrorType.EndStructureWithoutStructure; break; case BlockType.Module: ErrorType = SyntaxErrorType.EndModuleWithoutModule; break; case BlockType.Interface: ErrorType = SyntaxErrorType.EndInterfaceWithoutInterface; break; case BlockType.Enum: ErrorType = SyntaxErrorType.EndEnumWithoutEnum; break; case BlockType.Namespace: ErrorType = SyntaxErrorType.EndNamespaceWithoutNamespace; break; default: Debug.Assert(condition: false, "Unexpected."); break; } ReportSyntaxError(ErrorType, endDeclaration.Span); } private static SyntaxErrorType InvalidDeclarationTypeError(TreeType blockType) { switch (blockType) { case TreeType.PropertyDeclaration: return SyntaxErrorType.InvalidInsideProperty; case TreeType.ClassDeclaration: return SyntaxErrorType.InvalidInsideClass; case TreeType.StructureDeclaration: return SyntaxErrorType.InvalidInsideStructure; case TreeType.ModuleDeclaration: return SyntaxErrorType.InvalidInsideModule; case TreeType.InterfaceDeclaration: return SyntaxErrorType.InvalidInsideInterface; case TreeType.EnumDeclaration: return SyntaxErrorType.InvalidInsideEnum; case TreeType.NamespaceDeclaration: case TreeType.File: return SyntaxErrorType.InvalidInsideNamespace; default: { Debug.Assert(condition: false, "Unexpected."); SyntaxErrorType ErrorType = default(SyntaxErrorType); return ErrorType; } } } private void HandleUnexpectedToken(TokenType type) { SyntaxErrorType ErrorType; switch (type) { case TokenType.Comma: ErrorType = SyntaxErrorType.ExpectedComma; break; case TokenType.LeftParenthesis: ErrorType = SyntaxErrorType.ExpectedLeftParenthesis; break; case TokenType.RightParenthesis: ErrorType = SyntaxErrorType.ExpectedRightParenthesis; break; case TokenType.Equals: ErrorType = SyntaxErrorType.ExpectedEquals; break; case TokenType.As: ErrorType = SyntaxErrorType.ExpectedAs; break; case TokenType.RightCurlyBrace: ErrorType = SyntaxErrorType.ExpectedRightCurlyBrace; break; case TokenType.Period: ErrorType = SyntaxErrorType.ExpectedPeriod; break; case TokenType.Minus: ErrorType = SyntaxErrorType.ExpectedMinus; break; case TokenType.Is: ErrorType = SyntaxErrorType.ExpectedIs; break; case TokenType.GreaterThan: ErrorType = SyntaxErrorType.ExpectedGreaterThan; break; case TokenType.Of: ErrorType = SyntaxErrorType.ExpectedOf; break; default: Debug.Assert(condition: false, "Should give a more specific error."); ErrorType = SyntaxErrorType.SyntaxError; break; } ReportSyntaxError(ErrorType, Peek()); } private Location VerifyExpectedToken(TokenType type) { Token Token = Peek(); if (Token.Type == type) { return ReadLocation(); } HandleUnexpectedToken(type); return default(Location); } private bool CanEndStatement(Token token) { return token.Type == TokenType.Colon || token.Type == TokenType.LineTerminator || token.Type == TokenType.EndOfStream || token.Type == TokenType.Comment || (BlockContextStack.Count > 0 && CurrentBlockContextType() == TreeType.LineIfBlockStatement && token.Type == TokenType.Else); } private bool BeginsStatement(Token token) { if (!CanEndStatement(token)) { return false; } switch (token.Type) { case TokenType.AddHandler: case TokenType.Call: case TokenType.Case: case TokenType.Catch: case TokenType.Class: case TokenType.Const: case TokenType.Declare: case TokenType.Delegate: case TokenType.Dim: case TokenType.Do: case TokenType.Else: case TokenType.ElseIf: case TokenType.End: case TokenType.EndIf: case TokenType.Enum: case TokenType.Erase: case TokenType.Error: case TokenType.Event: case TokenType.Exit: case TokenType.Finally: case TokenType.For: case TokenType.Friend: case TokenType.Function: case TokenType.Get: case TokenType.GoSub: case TokenType.GoTo: case TokenType.If: case TokenType.Implements: case TokenType.Imports: case TokenType.Inherits: case TokenType.Interface: case TokenType.Loop: case TokenType.Module: case TokenType.MustInherit: case TokenType.MustOverride: case TokenType.Namespace: case TokenType.Narrowing: case TokenType.Next: case TokenType.NotInheritable: case TokenType.NotOverridable: case TokenType.Option: case TokenType.Overloads: case TokenType.Overridable: case TokenType.Overrides: case TokenType.Partial: case TokenType.Private: case TokenType.Property: case TokenType.Protected: case TokenType.Public: case TokenType.RaiseEvent: case TokenType.ReadOnly: case TokenType.ReDim: case TokenType.RemoveHandler: case TokenType.Resume: case TokenType.Return: case TokenType.Select: case TokenType.Shadows: case TokenType.Shared: case TokenType.Static: case TokenType.Stop: case TokenType.Structure: case TokenType.Sub: case TokenType.SyncLock: case TokenType.Throw: case TokenType.Try: case TokenType.Using: case TokenType.Wend: case TokenType.While: case TokenType.Widening: case TokenType.With: case TokenType.WithEvents: case TokenType.WriteOnly: case TokenType.Pound: return true; default: return false; } } private Token VerifyEndOfStatement() { Token NextToken = Peek(); Debug.Assert(NextToken.Type != TokenType.Comment, "Should have dealt with these by now!"); if (NextToken.Type == TokenType.LineTerminator || NextToken.Type == TokenType.EndOfStream) { AtBeginningOfLine = true; CanContinueWithoutLineTerminator = false; } else if (NextToken.Type == TokenType.Colon) { AtBeginningOfLine = false; } else if (NextToken.Type == TokenType.Else && CurrentBlockContextType() == TreeType.LineIfBlockStatement) { AtBeginningOfLine = false; } else { if (NextToken.Type != TokenType.End || CurrentBlockContextType() != TreeType.LineIfBlockStatement) { if (CanContinueWithoutLineTerminator) { return NextToken; } ResyncAt(); ReportSyntaxError(SyntaxErrorType.ExpectedEndOfStatement, NextToken); return VerifyEndOfStatement(); } AtBeginningOfLine = false; } return Read(); } private static bool MustEndStatement(Token token) { return token.Type == TokenType.Colon || token.Type == TokenType.EndOfStream || token.Type == TokenType.LineTerminator || token.Type == TokenType.Comment; } private Span SpanFrom(Location location) { Location EndLocation = ((Peek().Type != TokenType.EndOfStream) ? Peek().Span.Start : Scanner.Previous().Span.Finish); return new Span(location, EndLocation); } private Span SpanFrom(Token token) { Location StartLocation; Location EndLocation; if (token.Type == TokenType.EndOfStream && !Scanner.IsOnFirstToken) { StartLocation = Scanner.Previous().Span.Finish; EndLocation = StartLocation; } else { StartLocation = token.Span.Start; EndLocation = ((Peek().Type != TokenType.EndOfStream || Scanner.IsOnFirstToken) ? Peek().Span.Start : Scanner.Previous().Span.Finish); } return new Span(StartLocation, EndLocation); } private Span SpanFrom(Token startToken, Token endToken) { Location StartLocation; Location EndLocation; if (startToken.Type == TokenType.EndOfStream && !Scanner.IsOnFirstToken) { StartLocation = Scanner.Previous().Span.Finish; EndLocation = StartLocation; } else { StartLocation = startToken.Span.Start; EndLocation = ((endToken.Type == TokenType.EndOfStream && !Scanner.IsOnFirstToken) ? Scanner.Previous().Span.Finish : ((endToken.Span.Start.Index != startToken.Span.Start.Index) ? endToken.Span.Start : endToken.Span.Finish)); } return new Span(StartLocation, EndLocation); } private static Span SpanFrom(Token startToken, Tree endTree) { Span SpanFrom = new Span(startToken.Span.Start, endTree.Span.Finish); return SpanFrom; } private Span SpanFrom(Statement startStatement, Statement endStatement) { if (endStatement == null) { return this.SpanFrom(startStatement.Span.Start); } Span SpanFrom = new Span(startStatement.Span.Start, endStatement.Span.Start); return SpanFrom; } private SimpleName ParseSimpleName(bool allowKeyword) { if (Peek().Type == TokenType.Identifier) { IdentifierToken IdentifierToken = (IdentifierToken)Read(); return new SimpleName(IdentifierToken.Identifier, IdentifierToken.TypeCharacter, IdentifierToken.Escaped, IdentifierToken.Span); } if (IdentifierToken.IsKeyword(Peek().Type)) { IdentifierToken IdentifierToken2 = (IdentifierToken)Read(); if (!allowKeyword) { ReportSyntaxError(SyntaxErrorType.InvalidUseOfKeyword, IdentifierToken2); } return new SimpleName(IdentifierToken2.Identifier, IdentifierToken2.TypeCharacter, IdentifierToken2.Escaped, IdentifierToken2.Span); } ReportSyntaxError(SyntaxErrorType.ExpectedIdentifier, Peek()); return SimpleName.GetBadSimpleName(SpanFrom(Peek(), Peek())); } private Name ParseName(bool AllowGlobal) { Token Start = Peek(); bool QualificationRequired = false; Name Result; if (Start.Type == TokenType.Global) { if (!AllowGlobal) { ReportSyntaxError(SyntaxErrorType.InvalidUseOfGlobal, Peek()); } Read(); Result = new SpecialName(TreeType.GlobalNamespaceName, SpanFrom(Start)); QualificationRequired = true; } else { Result = ParseSimpleName(allowKeyword: false); } if (Peek().Type == TokenType.Period) { do { Location DotLocation = ReadLocation(); SimpleName Qualifier = ParseSimpleName(allowKeyword: true); Result = new QualifiedName(Result, DotLocation, Qualifier, SpanFrom(Start)); } while (Peek().Type == TokenType.Period); } else if (QualificationRequired) { ReportSyntaxError(SyntaxErrorType.ExpectedPeriod, Peek()); } return Result; } private VariableName ParseVariableName(bool allowExplicitArraySizes) { Token Start = Peek(); ArrayTypeName ArrayType = null; SimpleName Name = ParseSimpleName(allowKeyword: false); if (Peek().Type == TokenType.LeftParenthesis) { ArrayType = ParseArrayTypeName(null, null, allowExplicitArraySizes, innerArrayType: false); } return new VariableName(Name, ArrayType, SpanFrom(Start)); } private Name ParseNameListName(bool allowLeadingMeOrMyBase = false) { Token Start = Peek(); Name Result = ((Start.Type == TokenType.MyBase && allowLeadingMeOrMyBase) ? new SpecialName(TreeType.MyBaseName, SpanFrom(ReadLocation())) : ((Start.Type != TokenType.Me || !allowLeadingMeOrMyBase || Scanner.Version < LanguageVersion.VisualBasic80) ? ((Name)ParseSimpleName(allowKeyword: false)) : ((Name)new SpecialName(TreeType.MeName, SpanFrom(ReadLocation()))))); if (Peek().Type == TokenType.Period) { do { Location DotLocation = ReadLocation(); SimpleName Qualifier = ParseSimpleName(allowKeyword: true); Result = new QualifiedName(Result, DotLocation, Qualifier, SpanFrom(Start)); } while (Peek().Type == TokenType.Period); } else { ReportSyntaxError(SyntaxErrorType.ExpectedPeriod, Peek()); } return Result; } private TypeName ParseTypeName(bool allowArrayType, bool allowOpenType = false) { Token Start = Peek(); TypeName Result = null; IntrinsicType Types = default(IntrinsicType); switch (Start.Type) { case TokenType.Boolean: Types = IntrinsicType.Boolean; break; case TokenType.SByte: Types = IntrinsicType.SByte; break; case TokenType.Byte: Types = IntrinsicType.Byte; break; case TokenType.Short: Types = IntrinsicType.Short; break; case TokenType.UShort: Types = IntrinsicType.UShort; break; case TokenType.Integer: Types = IntrinsicType.Integer; break; case TokenType.UInteger: Types = IntrinsicType.UInteger; break; case TokenType.Long: Types = IntrinsicType.Long; break; case TokenType.ULong: Types = IntrinsicType.ULong; break; case TokenType.Decimal: Types = IntrinsicType.Decimal; break; case TokenType.Single: Types = IntrinsicType.Single; break; case TokenType.Double: Types = IntrinsicType.Double; break; case TokenType.Date: Types = IntrinsicType.Date; break; case TokenType.Char: Types = IntrinsicType.Char; break; case TokenType.String: Types = IntrinsicType.String; break; case TokenType.Object: Types = IntrinsicType.Object; break; case TokenType.Identifier: case TokenType.Global: Result = ParseNamedTypeName(allowGlobal: true, allowOpenType); break; default: ReportSyntaxError(SyntaxErrorType.ExpectedType, Start); Result = NamedTypeName.GetBadNamedType(SpanFrom(Start)); break; } if (Result == null) { Read(); Result = new IntrinsicTypeName(Types, Start.Span); } if (allowArrayType && Peek().Type == TokenType.LeftParenthesis) { return ParseArrayTypeName(Start, Result, allowExplicitSizes: false, innerArrayType: false); } return Result; } private NamedTypeName ParseNamedTypeName(bool allowGlobal, bool allowOpenType = false) { Token Start = Peek(); Name Name = ParseName(allowGlobal); if (Peek().Type == TokenType.LeftParenthesis) { Token LeftParenthesis = Read(); if (Peek().Type == TokenType.Of) { return new ConstructedTypeName(Name, ParseTypeArguments(LeftParenthesis, allowOpenType), SpanFrom(Start)); } Backtrack(LeftParenthesis); } return new NamedTypeName(Name, Name.Span); } private TypeArgumentCollection ParseTypeArguments(Token leftParenthesis, bool allowOpenType = false) { List TypeArguments = new List(); List CommaLocations = new List(); bool OpenType = false; Debug.Assert(Peek().Type == TokenType.Of); Location OfLocation = ReadLocation(); if ((Peek().Type == TokenType.Comma || Peek().Type == TokenType.RightParenthesis) && allowOpenType) { OpenType = true; } if (!OpenType || Peek().Type != TokenType.RightParenthesis) { do { if (TypeArguments.Count > 0 || OpenType) { CommaLocations.Add(ReadLocation()); } if (!OpenType) { TypeName TypeArgument = ParseTypeName(allowArrayType: true); if (ErrorInConstruct) { ResyncAt(TokenType.Comma, TokenType.RightParenthesis); } TypeArguments.Add(TypeArgument); } } while (ArrayBoundsContinue()); } Location RightParenthesisLocation = VerifyExpectedToken(TokenType.RightParenthesis); return new TypeArgumentCollection(OfLocation, TypeArguments, CommaLocations, RightParenthesisLocation, SpanFrom(leftParenthesis)); } private bool ArrayBoundsContinue() { Token NextToken = Peek(); if (NextToken.Type == TokenType.Comma) { return true; } if (NextToken.Type == TokenType.RightParenthesis || MustEndStatement(NextToken)) { return false; } ReportSyntaxError(SyntaxErrorType.ArgumentSyntax, NextToken); ResyncAt(TokenType.Comma, TokenType.RightParenthesis); if (Peek().Type == TokenType.Comma) { ErrorInConstruct = false; return true; } return false; } private ArrayTypeName ParseArrayTypeName(Token startType, TypeName elementType, bool allowExplicitSizes, bool innerArrayType) { Token ArgumentsStart = Peek(); List CommaLocations = new List(); Debug.Assert(Peek().Type == TokenType.LeftParenthesis); if (startType == null) { startType = Peek(); } Read(); List Arguments; if (Peek().Type == TokenType.RightParenthesis || Peek().Type == TokenType.Comma) { Arguments = null; while (Peek().Type == TokenType.Comma) { CommaLocations.Add(ReadLocation()); } } else { if (!allowExplicitSizes) { if (innerArrayType) { ReportSyntaxError(SyntaxErrorType.NoConstituentArraySizes, Peek()); } else { ReportSyntaxError(SyntaxErrorType.NoExplicitArraySizes, Peek()); } } Arguments = new List(); do { if (Arguments.Count > 0) { CommaLocations.Add(ReadLocation()); } Token SizeStart = Peek(); Expression Size = ParseExpression(Scanner.Version > LanguageVersion.VisualBasic71); if (ErrorInConstruct) { ResyncAt(TokenType.Comma, TokenType.RightParenthesis, TokenType.As); } Arguments.Add(new Argument(null, default(Location), Size, SpanFrom(SizeStart))); } while (ArrayBoundsContinue()); } Location RightParenthesisLocation = VerifyExpectedToken(TokenType.RightParenthesis); ArgumentCollection ArgumentCollection = new ArgumentCollection(Arguments, CommaLocations, RightParenthesisLocation, SpanFrom(ArgumentsStart)); if (Peek().Type == TokenType.LeftParenthesis) { elementType = ParseArrayTypeName(Peek(), elementType, allowExplicitSizes: false, innerArrayType: true); } return new ArrayTypeName(elementType, checked(CommaLocations.Count + 1), ArgumentCollection, SpanFrom(startType)); } private Initializer ParseInitializer() { if (Peek().Type == TokenType.LeftCurlyBrace) { return ParseAggregateInitializer(); } Expression Expression = ParseExpression(); return new ExpressionInitializer(Expression, Expression.Span); } private bool InitializersContinue() { Token NextToken = Peek(); if (NextToken.Type == TokenType.Comma) { return true; } if (NextToken.Type == TokenType.RightCurlyBrace || MustEndStatement(NextToken)) { return false; } ReportSyntaxError(SyntaxErrorType.InitializerSyntax, NextToken); ResyncAt(TokenType.Comma, TokenType.RightCurlyBrace); if (Peek().Type == TokenType.Comma) { ErrorInConstruct = false; return true; } return false; } private AggregateInitializer ParseAggregateInitializer() { Token Start = Peek(); List Initializers = new List(); List CommaLocations = new List(); Debug.Assert(Start.Type == TokenType.LeftCurlyBrace); Read(); if (Peek().Type != TokenType.RightCurlyBrace) { do { if (Initializers.Count > 0) { CommaLocations.Add(ReadLocation()); } Initializers.Add(ParseInitializer()); if (ErrorInConstruct) { ResyncAt(TokenType.Comma, TokenType.RightCurlyBrace); } } while (InitializersContinue()); } Location RightBracketLocation = VerifyExpectedToken(TokenType.RightCurlyBrace); return new AggregateInitializer(new InitializerCollection(Initializers, CommaLocations, RightBracketLocation, SpanFrom(Start)), SpanFrom(Start)); } private Argument ParseArgument(ref bool foundNamedArgument) { Token Start = Read(); if (Peek().Type == TokenType.ColonEquals) { if (!foundNamedArgument) { foundNamedArgument = true; } } else if (foundNamedArgument) { ReportSyntaxError(SyntaxErrorType.ExpectedNamedArgument, Start); foundNamedArgument = false; } Backtrack(Start); SimpleName Name; Location ColonEqualsLocation = default(Location); Expression Value; if (foundNamedArgument) { Name = ParseSimpleName(allowKeyword: true); ColonEqualsLocation = ReadLocation(); Value = ParseExpression(); } else { Name = null; Value = ParseExpression(); } if (ErrorInConstruct) { ResyncAt(TokenType.Comma, TokenType.RightParenthesis); if (Peek().Type == TokenType.Comma) { ErrorInConstruct = false; } } return new Argument(Name, ColonEqualsLocation, Value, SpanFrom(Start)); } private bool ArgumentsContinue() { Token NextToken = Peek(); if (NextToken.Type == TokenType.Comma) { return true; } if (NextToken.Type == TokenType.RightParenthesis || MustEndStatement(NextToken)) { return false; } if (NextToken.Type == TokenType.End && CurrentBlockContextType() == TreeType.LineIfBlockStatement) { return false; } ReportSyntaxError(SyntaxErrorType.ArgumentSyntax, NextToken); ResyncAt(TokenType.Comma, TokenType.RightParenthesis); if (Peek().Type == TokenType.Comma) { ErrorInConstruct = false; return true; } return false; } private ArgumentCollection ParseArguments(bool requireParenthesis = true) { Token Start = Peek(); List Arguments = new List(); List CommaLocations = new List(); if (Start.Type != TokenType.LeftParenthesis) { if (requireParenthesis) { return null; } } else { requireParenthesis = true; Read(); } if (Peek().Type != TokenType.RightParenthesis) { bool FoundNamedArgument = false; do { if (Arguments.Count > 0) { CommaLocations.Add(ReadLocation()); } Token ArgumentStart = Peek(); Argument Argument; if (ArgumentStart.Type == TokenType.Comma || ArgumentStart.Type == TokenType.RightParenthesis) { if (FoundNamedArgument) { ReportSyntaxError(SyntaxErrorType.ExpectedNamedArgument, Peek()); } Argument = null; } else { Argument = ParseArgument(ref FoundNamedArgument); } Arguments.Add(Argument); } while (ArgumentsContinue()); } Location RightParenthesisLocation = default(Location); if (Peek().Type == TokenType.RightParenthesis) { RightParenthesisLocation = ReadLocation(); } else if (requireParenthesis) { Token Current = Peek(); ResyncAt(TokenType.LeftParenthesis, TokenType.RightParenthesis); if (Peek().Type == TokenType.RightParenthesis) { ReportSyntaxError(SyntaxErrorType.SyntaxError, Peek()); RightParenthesisLocation = ReadLocation(); } else { Backtrack(Current); ReportSyntaxError(SyntaxErrorType.ExpectedRightParenthesis, Peek()); } } else { RightParenthesisLocation = Peek().Span.Start; } return new ArgumentCollection(Arguments, CommaLocations, RightParenthesisLocation, SpanFrom(Start)); } private LiteralExpression ParseLiteralExpression() { Token Start = Read(); switch (Start.Type) { case TokenType.False: case TokenType.True: return new BooleanLiteralExpression(Start.Type == TokenType.True, Start.Span); case TokenType.IntegerLiteral: { IntegerLiteralToken Literal6 = (IntegerLiteralToken)Start; return new IntegerLiteralExpression(Literal6.Literal, Literal6.IntegerBase, Literal6.TypeCharacter, Literal6.Span); } case TokenType.FloatingPointLiteral: { FloatingPointLiteralToken Literal4 = (FloatingPointLiteralToken)Start; return new FloatingPointLiteralExpression(Literal4.Literal, Literal4.TypeCharacter, Literal4.Span); } case TokenType.DecimalLiteral: { DecimalLiteralToken Literal2 = (DecimalLiteralToken)Start; return new DecimalLiteralExpression(Literal2.Literal, Literal2.TypeCharacter, Literal2.Span); } case TokenType.CharacterLiteral: { CharacterLiteralToken Literal3 = (CharacterLiteralToken)Start; return new CharacterLiteralExpression(Literal3.Literal, Literal3.Span); } case TokenType.StringLiteral: { StringLiteralToken Literal = (StringLiteralToken)Start; return new StringLiteralExpression(Literal.Literal, Literal.Span); } case TokenType.DateLiteral: { DateLiteralToken Literal5 = (DateLiteralToken)Start; return new DateLiteralExpression(Literal5.Literal, Literal5.Span); } default: Debug.Assert(condition: false, "Unexpected."); return null; } } private Expression ParseCastExpression() { Token Start = Read(); IntrinsicType OperatorType; switch (Start.Type) { case TokenType.CBool: OperatorType = IntrinsicType.Boolean; break; case TokenType.CChar: OperatorType = IntrinsicType.Char; break; case TokenType.CDate: OperatorType = IntrinsicType.Date; break; case TokenType.CDbl: OperatorType = IntrinsicType.Double; break; case TokenType.CByte: OperatorType = IntrinsicType.Byte; break; case TokenType.CShort: OperatorType = IntrinsicType.Short; break; case TokenType.CInt: OperatorType = IntrinsicType.Integer; break; case TokenType.CLng: OperatorType = IntrinsicType.Long; break; case TokenType.CSng: OperatorType = IntrinsicType.Single; break; case TokenType.CStr: OperatorType = IntrinsicType.String; break; case TokenType.CDec: OperatorType = IntrinsicType.Decimal; break; case TokenType.CObj: OperatorType = IntrinsicType.Object; break; case TokenType.CSByte: OperatorType = IntrinsicType.SByte; break; case TokenType.CUShort: OperatorType = IntrinsicType.UShort; break; case TokenType.CUInt: OperatorType = IntrinsicType.UInteger; break; case TokenType.CULng: OperatorType = IntrinsicType.ULong; break; default: Debug.Assert(condition: false, "Unexpected."); return null; } Location LeftParenthesisLocation = VerifyExpectedToken(TokenType.LeftParenthesis); Expression Operand = ParseExpression(); Location RightParenthesisLocation = VerifyExpectedToken(TokenType.RightParenthesis); return new IntrinsicCastExpression(OperatorType, LeftParenthesisLocation, Operand, RightParenthesisLocation, SpanFrom(Start)); } private Expression ParseCTypeExpression() { Token Start = Read(); Debug.Assert(Start.Type == TokenType.CType || Start.Type == TokenType.DirectCast || Start.Type == TokenType.TryCast); Location LeftParenthesisLocation = VerifyExpectedToken(TokenType.LeftParenthesis); Expression Operand = ParseExpression(); if (ErrorInConstruct) { ResyncAt(TokenType.Comma, TokenType.RightParenthesis); } Location CommaLocation = VerifyExpectedToken(TokenType.Comma); TypeName Target = ParseTypeName(allowArrayType: true); Location RightParenthesisLocation = VerifyExpectedToken(TokenType.RightParenthesis); if (Start.Type == TokenType.CType) { return new CTypeExpression(LeftParenthesisLocation, Operand, CommaLocation, Target, RightParenthesisLocation, SpanFrom(Start)); } if (Start.Type == TokenType.DirectCast) { return new DirectCastExpression(LeftParenthesisLocation, Operand, CommaLocation, Target, RightParenthesisLocation, SpanFrom(Start)); } return new TryCastExpression(LeftParenthesisLocation, Operand, CommaLocation, Target, RightParenthesisLocation, SpanFrom(Start)); } private Expression ParseInstanceExpression() { Token Start = Read(); InstanceType InstanceType = default(InstanceType); switch (Start.Type) { case TokenType.Me: InstanceType = InstanceType.Me; break; case TokenType.MyClass: InstanceType = InstanceType.MyClass; if (Peek().Type != TokenType.Period) { ReportSyntaxError(SyntaxErrorType.ExpectedPeriodAfterMyClass, Start); } break; case TokenType.MyBase: InstanceType = InstanceType.MyBase; if (Peek().Type != TokenType.Period) { ReportSyntaxError(SyntaxErrorType.ExpectedPeriodAfterMyBase, Start); } break; default: Debug.Assert(condition: false, "Unexpected."); break; } return new InstanceExpression(InstanceType, Start.Span); } private Expression ParseParentheticalExpression() { Token Start = Read(); Debug.Assert(Start.Type == TokenType.LeftParenthesis); Expression Operand = ParseExpression(); Location RightParenthesisLocation = VerifyExpectedToken(TokenType.RightParenthesis); return new ParentheticalExpression(Operand, RightParenthesisLocation, SpanFrom(Start)); } private Expression ParseSimpleNameExpression() { Token Start = Peek(); return new SimpleNameExpression(ParseSimpleName(allowKeyword: false), SpanFrom(Start)); } private Expression ParseDotBangExpression(Token start, Expression terminal) { Debug.Assert(Peek().Type == TokenType.Period || Peek().Type == TokenType.Exclamation); Token DotBang = Read(); SimpleName Name = ParseSimpleName(allowKeyword: true); if (DotBang.Type == TokenType.Period) { return new QualifiedExpression(terminal, DotBang.Span.Start, Name, SpanFrom(start)); } return new DictionaryLookupExpression(terminal, DotBang.Span.Start, Name, SpanFrom(start)); } private Expression ParseCallOrIndexExpression(Token start, Expression terminal) { ArgumentCollection Arguments = ParseArguments(); return new CallOrIndexExpression(terminal, Arguments, SpanFrom(start)); } private Expression ParseTypeOfExpression() { Token Start = Peek(); Debug.Assert(Start.Type == TokenType.TypeOf); Read(); Expression Value = ParseBinaryOperatorExpression(PrecedenceLevel.Relational); if (ErrorInConstruct) { ResyncAt(TokenType.Is); } Location IsLocation = VerifyExpectedToken(TokenType.Is); TypeName Target = ParseTypeName(allowArrayType: true); return new TypeOfExpression(Value, IsLocation, Target, SpanFrom(Start)); } private Expression ParseGetTypeExpression() { Token Start = Read(); Debug.Assert(Start.Type == TokenType.GetType); Location LeftParenthesisLocation = VerifyExpectedToken(TokenType.LeftParenthesis); TypeName Target = ParseTypeName(allowArrayType: true, allowOpenType: true); Location RightParenthesisLocation = VerifyExpectedToken(TokenType.RightParenthesis); return new GetTypeExpression(LeftParenthesisLocation, Target, RightParenthesisLocation, SpanFrom(Start)); } private Expression ParseNewExpression() { Token Start = Read(); Debug.Assert(Start.Type == TokenType.New); Token TypeStart = Peek(); TypeName Type = ParseTypeName(allowArrayType: false); if (ErrorInConstruct) { ResyncAt(TokenType.LeftParenthesis); } Token ArgumentsStart = Peek(); ArgumentCollection Arguments = ParseArguments(); if ((Peek().Type == TokenType.LeftCurlyBrace || Peek().Type == TokenType.LeftParenthesis) && Arguments != null) { Backtrack(ArgumentsStart); ArrayTypeName ArrayType = ParseArrayTypeName(TypeStart, Type, allowExplicitSizes: true, innerArrayType: false); if (Peek().Type == TokenType.LeftCurlyBrace) { AggregateInitializer Initializer = ParseAggregateInitializer(); return new NewAggregateExpression(ArrayType, Initializer, SpanFrom(Start)); } HandleUnexpectedToken(TokenType.LeftCurlyBrace); } return new NewExpression(Type, Arguments, SpanFrom(Start)); } private Expression ParseTerminalExpression() { Token Start = Peek(); Expression Terminal; switch (Start.Type) { case TokenType.Identifier: Terminal = ParseSimpleNameExpression(); break; case TokenType.StringLiteral: case TokenType.CharacterLiteral: case TokenType.DateLiteral: case TokenType.IntegerLiteral: case TokenType.FloatingPointLiteral: case TokenType.DecimalLiteral: case TokenType.False: case TokenType.True: Terminal = ParseLiteralExpression(); break; case TokenType.CBool: case TokenType.CByte: case TokenType.CChar: case TokenType.CDate: case TokenType.CDec: case TokenType.CDbl: case TokenType.CInt: case TokenType.CLng: case TokenType.CObj: case TokenType.CSByte: case TokenType.CShort: case TokenType.CSng: case TokenType.CStr: case TokenType.CUInt: case TokenType.CULng: case TokenType.CUShort: Terminal = ParseCastExpression(); break; case TokenType.CType: case TokenType.DirectCast: case TokenType.TryCast: Terminal = ParseCTypeExpression(); break; case TokenType.Me: case TokenType.MyBase: case TokenType.MyClass: Terminal = ParseInstanceExpression(); break; case TokenType.Global: Terminal = new GlobalExpression(Read().Span); if (Peek().Type != TokenType.Period) { ReportSyntaxError(SyntaxErrorType.ExpectedPeriodAfterGlobal, Start); } break; case TokenType.Nothing: Terminal = new NothingExpression(Read().Span); break; case TokenType.LeftParenthesis: Terminal = ParseParentheticalExpression(); break; case TokenType.Exclamation: case TokenType.Period: Terminal = ParseDotBangExpression(Start, null); break; case TokenType.TypeOf: Terminal = ParseTypeOfExpression(); break; case TokenType.GetType: Terminal = ParseGetTypeExpression(); break; case TokenType.New: Terminal = ParseNewExpression(); break; case TokenType.Boolean: case TokenType.Byte: case TokenType.Char: case TokenType.Date: case TokenType.Decimal: case TokenType.Double: case TokenType.Integer: case TokenType.Long: case TokenType.Object: case TokenType.Short: case TokenType.Single: case TokenType.String: Terminal = new SimpleNameExpression(ParseSimpleName(allowKeyword: true), SpanFrom(Start)); if (Scanner.Peek().Type == TokenType.Period) { Terminal = ParseDotBangExpression(Start, Terminal); } break; default: ReportSyntaxError(SyntaxErrorType.ExpectedExpression, Peek()); Terminal = Expression.GetBadExpression(SpanFrom(Peek(), Peek())); break; } while (true) { Token NextToken = Peek(); if (NextToken.Type == TokenType.Period || NextToken.Type == TokenType.Exclamation) { Terminal = ParseDotBangExpression(Start, Terminal); continue; } if (NextToken.Type == TokenType.LeftParenthesis) { Token LeftParenthesis = Read(); if (Peek().Type == TokenType.Of) { return new GenericQualifiedExpression(Terminal, ParseTypeArguments(LeftParenthesis), SpanFrom(Start)); } Backtrack(LeftParenthesis); Terminal = ParseCallOrIndexExpression(Start, Terminal); continue; } break; } return Terminal; } private Expression ParseUnaryOperatorExpression() { Token Start = Peek(); OperatorType OperatorType; Expression Operand; switch (Start.Type) { case TokenType.Minus: OperatorType = OperatorType.Negate; break; case TokenType.Plus: OperatorType = OperatorType.UnaryPlus; break; case TokenType.Not: OperatorType = OperatorType.Not; break; case TokenType.AddressOf: Read(); Operand = ParseBinaryOperatorExpression(PrecedenceLevel.None); return new AddressOfExpression(Operand, SpanFrom(Start, Operand)); default: return ParseTerminalExpression(); } Read(); Operand = ParseBinaryOperatorExpression(GetOperatorPrecedence(OperatorType)); return new UnaryOperatorExpression(OperatorType, Operand, SpanFrom(Start, Operand)); } private Expression ParseBinaryOperatorExpression(PrecedenceLevel pendingPrecedence, bool allowRange = false) { Token Start = Peek(); Expression Expression = ParseUnaryOperatorExpression(); while (true) { OperatorType OperatorType = GetBinaryOperator(Peek().Type, allowRange); if (OperatorType == OperatorType.None) { break; } PrecedenceLevel Precedence = GetOperatorPrecedence(OperatorType); if (Precedence <= pendingPrecedence) { break; } Location OperatorLocation = ReadLocation(); Expression Right = ParseBinaryOperatorExpression(Precedence); Expression = new BinaryOperatorExpression(Expression, OperatorType, OperatorLocation, Right, SpanFrom(Start, Right)); } return Expression; } private ExpressionCollection ParseExpressionList(bool requireExpression = false) { Token Start = Peek(); List Expressions = new List(); List CommaLocations = new List(); if (CanEndStatement(Start) && !requireExpression) { return null; } do { if (Expressions.Count > 0) { CommaLocations.Add(ReadLocation()); } Expressions.Add(ParseExpression()); if (ErrorInConstruct) { ResyncAt(TokenType.Comma); } } while (Peek().Type == TokenType.Comma); if (Expressions.Count == 0 && CommaLocations.Count == 0) { return null; } return new ExpressionCollection(Expressions, CommaLocations, SpanFrom(Start)); } private Expression ParseExpression(bool allowRange = false) { return ParseBinaryOperatorExpression(PrecedenceLevel.None, allowRange); } private Statement ParseExpressionStatement(TreeType type, bool operandOptional) { Token Start = Peek(); Expression Operand = null; Read(); if (!operandOptional || !CanEndStatement(Peek())) { Operand = ParseExpression(); } if (ErrorInConstruct) { ResyncAt(); } switch (type) { case TreeType.ReturnStatement: return new ReturnStatement(Operand, SpanFrom(Start), ParseTrailingComments()); case TreeType.ErrorStatement: return new ErrorStatement(Operand, SpanFrom(Start), ParseTrailingComments()); case TreeType.ThrowStatement: return new ThrowStatement(Operand, SpanFrom(Start), ParseTrailingComments()); default: Debug.Assert(condition: false, "Unexpected!"); return null; } } private void ParseLabelReference(ref SimpleName name, ref bool isLineNumber) { Token Start = Peek(); if (Start.Type == TokenType.Identifier) { name = ParseSimpleName(allowKeyword: false); isLineNumber = false; } else if (Start.Type == TokenType.IntegerLiteral) { IntegerLiteralToken IntegerLiteral = (IntegerLiteralToken)Start; if (IntegerLiteral.TypeCharacter != 0) { ReportSyntaxError(SyntaxErrorType.SyntaxError, Start); } name = new SimpleName(Conversions.ToString(IntegerLiteral.Literal), TypeCharacter.None, escaped: false, IntegerLiteral.Span); isLineNumber = true; Read(); } else { ReportSyntaxError(SyntaxErrorType.ExpectedIdentifier, Start); name = SimpleName.GetBadSimpleName(SpanFrom(Start)); isLineNumber = false; } } private Statement ParseGotoStatement() { Token Start = Peek(); SimpleName Name = null; Read(); bool IsLineNumber = default(bool); ParseLabelReference(ref Name, ref IsLineNumber); if (ErrorInConstruct) { ResyncAt(); } return new GotoStatement(Name, IsLineNumber, SpanFrom(Start), ParseTrailingComments()); } private Statement ParseContinueStatement() { Token Start = Peek(); Read(); BlockType ContinueType = GetContinueType(Peek().Type); Location ContinueArgumentLocation = default(Location); if (ContinueType == BlockType.None) { ReportSyntaxError(SyntaxErrorType.ExpectedContinueKind, Peek()); ResyncAt(); } else { ContinueArgumentLocation = ReadLocation(); } return new ContinueStatement(ContinueType, ContinueArgumentLocation, SpanFrom(Start), ParseTrailingComments()); } private Statement ParseExitStatement() { Token Start = Peek(); Read(); BlockType ExitType = GetExitType(Peek().Type); Location ExitArgumentLocation = default(Location); if (ExitType == BlockType.None) { ReportSyntaxError(SyntaxErrorType.ExpectedExitKind, Peek()); ResyncAt(); } else { ExitArgumentLocation = ReadLocation(); } return new ExitStatement(ExitType, ExitArgumentLocation, SpanFrom(Start), ParseTrailingComments()); } private Statement ParseEndStatement() { Token Start = Read(); BlockType EndType = GetBlockType(Peek().Type); if (EndType == BlockType.None) { return new EndStatement(SpanFrom(Start), ParseTrailingComments()); } return new EndBlockStatement(EndType, ReadLocation(), SpanFrom(Start), ParseTrailingComments()); } private Statement ParseWendStatement() { Token Start = Read(); return new EndBlockStatement(BlockType.While, Start.Span.Finish, SpanFrom(Start), ParseTrailingComments()); } private Statement ParseRaiseEventStatement() { Token Start = Peek(); Read(); SimpleName Name = ParseSimpleName(allowKeyword: true); if (ErrorInConstruct) { ResyncAt(); } ArgumentCollection Arguments = ParseArguments(); return new RaiseEventStatement(Name, Arguments, SpanFrom(Start), ParseTrailingComments()); } private Statement ParseHandlerStatement() { Token Start = Peek(); Read(); Expression EventName = ParseExpression(); if (ErrorInConstruct) { ResyncAt(TokenType.Comma); } Location CommaLocation = VerifyExpectedToken(TokenType.Comma); Expression DelegateExpression = ParseExpression(); if (ErrorInConstruct) { ResyncAt(); } if (Start.Type == TokenType.AddHandler) { return new AddHandlerStatement(EventName, CommaLocation, DelegateExpression, SpanFrom(Start), ParseTrailingComments()); } return new RemoveHandlerStatement(EventName, CommaLocation, DelegateExpression, SpanFrom(Start), ParseTrailingComments()); } private Statement ParseOnErrorStatement() { Token Start = Read(); SimpleName Name = null; Location ErrorLocation = default(Location); Location ResumeOrGoToLocation = default(Location); Location NextOrZeroOrMinusLocation = default(Location); OnErrorType OnErrorType; Location OneLocation = default(Location); bool IsLineNumber = default(bool); if (Peek().Type == TokenType.Error) { ErrorLocation = ReadLocation(); Token NextToken = Peek(); if (NextToken.Type == TokenType.Resume) { ResumeOrGoToLocation = ReadLocation(); if (Peek().Type == TokenType.Next) { NextOrZeroOrMinusLocation = ReadLocation(); } else { ReportSyntaxError(SyntaxErrorType.ExpectedNext, Peek()); } OnErrorType = OnErrorType.Next; } else if (NextToken.Type == TokenType.GoTo) { ResumeOrGoToLocation = ReadLocation(); NextToken = Peek(); if (NextToken.Type == TokenType.IntegerLiteral && ((IntegerLiteralToken)NextToken).Literal == 0) { NextOrZeroOrMinusLocation = ReadLocation(); OnErrorType = OnErrorType.Zero; } else { if (NextToken.Type == TokenType.Minus) { NextOrZeroOrMinusLocation = ReadLocation(); Token NextNextToken = Peek(); if (NextNextToken.Type == TokenType.IntegerLiteral && ((IntegerLiteralToken)NextNextToken).Literal == 1) { OneLocation = ReadLocation(); OnErrorType = OnErrorType.MinusOne; goto IL_01ab; } Backtrack(NextToken); } OnErrorType = OnErrorType.Label; ParseLabelReference(ref Name, ref IsLineNumber); if (ErrorInConstruct) { ResyncAt(); } } } else { ReportSyntaxError(SyntaxErrorType.ExpectedResumeOrGoto, Peek()); OnErrorType = OnErrorType.Bad; ResyncAt(); } } else { ReportSyntaxError(SyntaxErrorType.ExpectedError, Peek()); OnErrorType = OnErrorType.Bad; ResyncAt(); } goto IL_01ab; IL_01ab: return new OnErrorStatement(OnErrorType, ErrorLocation, ResumeOrGoToLocation, NextOrZeroOrMinusLocation, OneLocation, Name, IsLineNumber, SpanFrom(Start), ParseTrailingComments()); } private Statement ParseResumeStatement() { Token Start = Read(); ResumeType ResumeType = ResumeType.None; SimpleName Name = null; Location NextLocation = default(Location); bool IsLineNumber = default(bool); if (!CanEndStatement(Peek())) { if (Peek().Type == TokenType.Next) { NextLocation = ReadLocation(); ResumeType = ResumeType.Next; } else { ParseLabelReference(ref Name, ref IsLineNumber); ResumeType = ((!ErrorInConstruct) ? ResumeType.Label : ResumeType.None); } } return new ResumeStatement(ResumeType, NextLocation, Name, IsLineNumber, SpanFrom(Start), ParseTrailingComments()); } private Statement ParseReDimStatement() { Token Start = Read(); Location PreserveLocation = default(Location); if (Peek().AsUnreservedKeyword() == TokenType.Preserve) { PreserveLocation = ReadLocation(); } ExpressionCollection Variables = ParseExpressionList(requireExpression: true); return new ReDimStatement(PreserveLocation, Variables, SpanFrom(Start), ParseTrailingComments()); } private Statement ParseEraseStatement() { Token Start = Read(); ExpressionCollection Variables = ParseExpressionList(requireExpression: true); return new EraseStatement(Variables, SpanFrom(Start), ParseTrailingComments()); } private Statement ParseCallStatement(Expression target = null) { Token Start = Peek(); ArgumentCollection Arguments = null; Location StartLocation; Location CallLocation = default(Location); if (target == null) { StartLocation = Start.Span.Start; if (Start.Type == TokenType.Call) { CallLocation = ReadLocation(); } target = ParseExpression(); if (ErrorInConstruct) { ResyncAt(); } } else { StartLocation = target.Span.Start; } if (target.Type == TreeType.CallOrIndexExpression) { CallOrIndexExpression CallOrIndexExpression = (CallOrIndexExpression)target; target = CallOrIndexExpression.TargetExpression; Arguments = CallOrIndexExpression.Arguments; } else if (!MustEndStatement(Peek())) { Arguments = ParseArguments(requireParenthesis: false); } return new CallStatement(CallLocation, target, Arguments, SpanFrom(StartLocation), ParseTrailingComments()); } private Statement ParseMidAssignmentStatement() { Token Start = Read(); IdentifierToken Identifier = (IdentifierToken)Start; Location LengthCommaLocation = default(Location); Expression LengthExpression = null; bool HasTypeCharacter = default(bool); if (Identifier.TypeCharacter == TypeCharacter.StringSymbol) { HasTypeCharacter = true; } else if (Identifier.TypeCharacter != 0) { goto IL_0196; } if (Peek().Type == TokenType.LeftParenthesis) { Location LeftParenthesisLocation = VerifyExpectedToken(TokenType.LeftParenthesis); Expression Target = ParseExpression(); if (ErrorInConstruct) { ResyncAt(TokenType.Comma); } Location StartCommaLocation = VerifyExpectedToken(TokenType.Comma); Expression StartExpression = ParseExpression(); if (ErrorInConstruct) { ResyncAt(TokenType.Comma, TokenType.RightParenthesis); } if (Peek().Type == TokenType.Comma) { LengthCommaLocation = VerifyExpectedToken(TokenType.Comma); LengthExpression = ParseExpression(); if (ErrorInConstruct) { ResyncAt(TokenType.RightParenthesis); } } Location RightParenthesisLocation = VerifyExpectedToken(TokenType.RightParenthesis); Location OperatorLocation = VerifyExpectedToken(TokenType.Equals); Expression Source = ParseExpression(); if (ErrorInConstruct) { ResyncAt(); } return new MidAssignmentStatement(HasTypeCharacter, LeftParenthesisLocation, Target, StartCommaLocation, StartExpression, LengthCommaLocation, LengthExpression, RightParenthesisLocation, OperatorLocation, Source, SpanFrom(Start), ParseTrailingComments()); } goto IL_0196; IL_0196: Backtrack(Start); return null; } private Statement ParseAssignmentStatement(Expression target, bool isSetStatement) { Token Operator = Read(); OperatorType CompoundOperator = GetCompoundAssignmentOperatorType(Operator.Type); Expression Source = ParseExpression(); if (ErrorInConstruct) { ResyncAt(); } if (CompoundOperator == OperatorType.None) { return new AssignmentStatement(target, Operator.Span.Start, Source, SpanFrom(target.Span.Start), ParseTrailingComments(), isSetStatement); } return new CompoundAssignmentStatement(CompoundOperator, target, Operator.Span.Start, Source, SpanFrom(target.Span.Start), ParseTrailingComments()); } private Statement ParseLocalDeclarationStatement() { Token Start = Peek(); ModifierCollection Modifiers = ParseDeclarationModifierList(); ValidateModifierList(Modifiers, ModifierTypes.Static | ModifierTypes.Dim | ModifierTypes.Const); if (Modifiers == null) { ReportSyntaxError(SyntaxErrorType.ExpectedModifier, Peek()); } else if (Modifiers.Count > 1) { ReportSyntaxError(SyntaxErrorType.InvalidVariableModifiers, Modifiers.Span); } return new LocalDeclarationStatement(Modifiers, ParseVariableDeclarators(), SpanFrom(Start), ParseTrailingComments()); } private Statement ParseLabelStatement() { SimpleName Name = null; Token Start = Peek(); bool IsLineNumber = default(bool); ParseLabelReference(ref Name, ref IsLineNumber); return new LabelStatement(Name, IsLineNumber, SpanFrom(Start), ParseTrailingComments()); } private Statement ParseExpressionBlockStatement(TreeType blockType) { Token Start = Read(); Expression Expression = ParseExpression(); Statement EndStatement = null; List Comments = null; if (ErrorInConstruct) { ResyncAt(); } StatementCollection StatementCollection = ParseStatementBlock(SpanFrom(Start), blockType, ref Comments, ref EndStatement); switch (blockType) { case TreeType.WithBlockStatement: return new WithBlockStatement(Expression, StatementCollection, (EndBlockStatement)EndStatement, SpanFrom(Start), Comments); case TreeType.SyncLockBlockStatement: return new SyncLockBlockStatement(Expression, StatementCollection, (EndBlockStatement)EndStatement, SpanFrom(Start), Comments); case TreeType.WhileBlockStatement: return new WhileBlockStatement(Expression, StatementCollection, (EndBlockStatement)EndStatement, SpanFrom(Start), Comments); default: Debug.Assert(condition: false, "Unexpected!"); return null; } } private Statement ParseUsingBlockStatement() { Token Start = Read(); Expression Expression = null; VariableDeclaratorCollection VariableDeclarators = null; Statement EndStatement = null; List Comments = null; Token NextToken = PeekAheadOne(); if (NextToken.Type == TokenType.As || NextToken.Type == TokenType.Equals) { VariableDeclarators = ParseVariableDeclarators(); } else { Expression = ParseExpression(); } if (ErrorInConstruct) { ResyncAt(); } StatementCollection StatementCollection = ParseStatementBlock(SpanFrom(Start), TreeType.UsingBlockStatement, ref Comments, ref EndStatement); if (Expression == null) { return new UsingBlockStatement(VariableDeclarators, StatementCollection, (EndBlockStatement)EndStatement, SpanFrom(Start), Comments); } return new UsingBlockStatement(Expression, StatementCollection, (EndBlockStatement)EndStatement, SpanFrom(Start), Comments); } private Expression ParseOptionalWhileUntilClause(ref bool isWhile, ref Location whileOrUntilLocation) { Expression Expression = null; if (!CanEndStatement(Peek())) { Token Token = Peek(); if (Token.Type == TokenType.While || Token.AsUnreservedKeyword() == TokenType.Until) { isWhile = Token.Type == TokenType.While; whileOrUntilLocation = ReadLocation(); Expression = ParseExpression(); if (ErrorInConstruct) { ResyncAt(); } } else { ReportSyntaxError(SyntaxErrorType.SyntaxError, Peek()); ResyncAt(); } } return Expression; } private Statement ParseDoBlockStatement() { Token Start = Read(); Statement EndStatement = null; List Comments = null; bool IsWhile = default(bool); Location WhileOrUntilLocation = default(Location); Expression Expression = ParseOptionalWhileUntilClause(ref IsWhile, ref WhileOrUntilLocation); StatementCollection StatementCollection = ParseStatementBlock(SpanFrom(Start), TreeType.DoBlockStatement, ref Comments, ref EndStatement); LoopStatement LoopStatement = (LoopStatement)EndStatement; if (Expression != null && LoopStatement != null && LoopStatement.Expression != null) { ReportSyntaxError(SyntaxErrorType.LoopDoubleCondition, LoopStatement.Expression.Span); } return new DoBlockStatement(Expression, IsWhile, WhileOrUntilLocation, StatementCollection, LoopStatement, SpanFrom(Start), Comments); } private Statement ParseLoopStatement() { Token Start = Read(); bool IsWhile = default(bool); Location WhileOrUntilLocation = default(Location); Expression Expression = ParseOptionalWhileUntilClause(ref IsWhile, ref WhileOrUntilLocation); return new LoopStatement(Expression, IsWhile, WhileOrUntilLocation, SpanFrom(Start), ParseTrailingComments()); } private Expression ParseForLoopControlVariable(ref VariableDeclarator variableDeclarator) { Token Start = Peek(); if (Start.Type == TokenType.Identifier) { Token NextToken = PeekAheadOne(); Expression Expression = null; if (NextToken.Type == TokenType.As) { variableDeclarator = ParseForLoopVariableDeclarator(ref Expression); return Expression; } if (NextToken.Type == TokenType.LeftParenthesis && PeekAheadFor(TokenType.As, TokenType.In, TokenType.Equals) == TokenType.As) { variableDeclarator = ParseForLoopVariableDeclarator(ref Expression); return Expression; } } return ParseBinaryOperatorExpression(PrecedenceLevel.Relational); } private Statement ParseForBlockStatement() { Token Start = Read(); if (Peek().Type != TokenType.Each) { Expression LowerBoundExpression = null; Expression UpperBoundExpression = null; Expression StepExpression = null; VariableDeclarator VariableDeclarator2 = null; Statement NextStatement2 = null; List Comments2 = null; Expression ControlExpression2 = ParseForLoopControlVariable(ref VariableDeclarator2); if (ErrorInConstruct) { ResyncAt(TokenType.Equals, TokenType.To); } Location EqualLocation = default(Location); if (Peek().Type == TokenType.Equals) { EqualLocation = ReadLocation(); LowerBoundExpression = ParseExpression(); if (ErrorInConstruct) { ResyncAt(TokenType.To); } } else { ReportSyntaxError(SyntaxErrorType.SyntaxError, Peek()); ResyncAt(TokenType.To); } Location ToLocation = default(Location); if (Peek().Type == TokenType.To) { ToLocation = ReadLocation(); UpperBoundExpression = ParseExpression(); if (ErrorInConstruct) { ResyncAt(TokenType.Step); } } else { ReportSyntaxError(SyntaxErrorType.SyntaxError, Peek()); ResyncAt(TokenType.Step); } Location StepLocation = default(Location); if (Peek().Type == TokenType.Step) { StepLocation = ReadLocation(); StepExpression = ParseExpression(); if (ErrorInConstruct) { ResyncAt(); } } StatementCollection Statements2 = ParseStatementBlock(SpanFrom(Start), TreeType.ForBlockStatement, ref Comments2, ref NextStatement2); return new ForBlockStatement(ControlExpression2, VariableDeclarator2, EqualLocation, LowerBoundExpression, ToLocation, UpperBoundExpression, StepLocation, StepExpression, Statements2, (NextStatement)NextStatement2, SpanFrom(Start), Comments2); } VariableDeclarator VariableDeclarator = null; Expression CollectionExpression = null; Statement NextStatement = null; List Comments = null; Location EachLocation = ReadLocation(); Expression ControlExpression = ParseForLoopControlVariable(ref VariableDeclarator); if (ErrorInConstruct) { ResyncAt(TokenType.In); } Location InLocation = default(Location); if (Peek().Type == TokenType.In) { InLocation = ReadLocation(); CollectionExpression = ParseExpression(); if (ErrorInConstruct) { ResyncAt(); } } else { ReportSyntaxError(SyntaxErrorType.SyntaxError, Peek()); ResyncAt(); } StatementCollection Statements = ParseStatementBlock(SpanFrom(Start), TreeType.ForBlockStatement, ref Comments, ref NextStatement); return new ForEachBlockStatement(EachLocation, ControlExpression, VariableDeclarator, InLocation, CollectionExpression, Statements, (NextStatement)NextStatement, SpanFrom(Start), Comments); } private Statement ParseNextStatement() { Token Start = Read(); return new NextStatement(ParseExpressionList(), SpanFrom(Start), ParseTrailingComments()); } private Statement ParseTryBlockStatement() { Token Start = Read(); Statement EndBlockStatement = null; List CatchBlocks = new List(); StatementCollection CatchBlockList = null; FinallyBlockStatement FinallyBlock = null; List Comments = null; StatementCollection TryStatementList = ParseStatementBlock(SpanFrom(Start), TreeType.TryBlockStatement, ref Comments, ref EndBlockStatement); while (EndBlockStatement != null && EndBlockStatement.Type != TreeType.EndBlockStatement) { if (EndBlockStatement.Type == TreeType.CatchStatement) { CatchStatement CatchStatement = (CatchStatement)EndBlockStatement; Span span = CatchStatement.Span; List Comments2 = null; StatementCollection StatementCollection = ParseStatementBlock(span, TreeType.CatchBlockStatement, ref Comments2, ref EndBlockStatement); CatchBlocks.Add(new CatchBlockStatement(CatchStatement, StatementCollection, SpanFrom(CatchStatement, EndBlockStatement), null)); } else { FinallyStatement FinallyStatement = (FinallyStatement)EndBlockStatement; Span span2 = FinallyStatement.Span; List Comments2 = null; StatementCollection StatementCollection = ParseStatementBlock(span2, TreeType.FinallyBlockStatement, ref Comments2, ref EndBlockStatement); FinallyBlock = new FinallyBlockStatement(FinallyStatement, StatementCollection, SpanFrom(FinallyStatement, EndBlockStatement), null); } } if (CatchBlocks.Count > 0) { CatchBlockList = new StatementCollection(CatchBlocks, null, new Span(((CatchBlockStatement)CatchBlocks[0]).Span.Start, ((CatchBlockStatement)CatchBlocks[checked(CatchBlocks.Count - 1)]).Span.Finish)); } return new TryBlockStatement(TryStatementList, CatchBlockList, FinallyBlock, (EndBlockStatement)EndBlockStatement, SpanFrom(Start), Comments); } private Statement ParseCatchStatement() { Token Start = Read(); SimpleName Name = null; TypeName Type = null; Expression Filter = null; Location AsLocation = default(Location); if (Peek().Type == TokenType.Identifier) { Name = ParseSimpleName(allowKeyword: false); if (Peek().Type == TokenType.As) { AsLocation = ReadLocation(); Type = ParseTypeName(allowArrayType: false); if (ErrorInConstruct) { ResyncAt(TokenType.When); } } } Location WhenLocation = default(Location); if (Peek().Type == TokenType.When) { WhenLocation = ReadLocation(); Filter = ParseExpression(); } return new CatchStatement(Name, AsLocation, Type, WhenLocation, Filter, SpanFrom(Start), ParseTrailingComments()); } private Statement ParseCaseStatement() { Token Start = Read(); Token CasesStart = Peek(); if (Peek().Type == TokenType.Else) { return new CaseElseStatement(ReadLocation(), SpanFrom(Start), ParseTrailingComments()); } List CommaLocations = new List(); List Cases = new List(); do { if (Cases.Count > 0) { CommaLocations.Add(ReadLocation()); } Cases.Add(ParseCase()); } while (Peek().Type == TokenType.Comma); return new CaseStatement(new CaseClauseCollection(Cases, CommaLocations, SpanFrom(CasesStart)), SpanFrom(Start), ParseTrailingComments()); } private Statement ParseSelectBlockStatement() { Token Start = Read(); Statement EndBlockStatement = null; List CaseBlocks = new List(); StatementCollection CaseBlockList = null; CaseElseBlockStatement CaseElseBlockStatement = null; List Comments = null; Location CaseLocation = default(Location); if (Peek().Type == TokenType.Case) { CaseLocation = ReadLocation(); } Expression SelectExpression = ParseExpression(); if (ErrorInConstruct) { ResyncAt(); } StatementCollection Statements = ParseStatementBlock(SpanFrom(Start), TreeType.SelectBlockStatement, ref Comments, ref EndBlockStatement); if (Statements != null && Statements.Count != 0) { foreach (Statement Statement in Statements) { if (Statement.Type != TreeType.EmptyStatement) { ReportSyntaxError(SyntaxErrorType.ExpectedCase, Statements.Span); } } } while (EndBlockStatement != null && EndBlockStatement.Type != TreeType.EndBlockStatement) { Statement CaseStatement = EndBlockStatement; if (CaseStatement.Type == TreeType.CaseStatement) { Span span = CaseStatement.Span; List Comments2 = null; StatementCollection CaseStatements = ParseStatementBlock(span, TreeType.CaseBlockStatement, ref Comments2, ref EndBlockStatement); CaseBlocks.Add(new CaseBlockStatement((CaseStatement)CaseStatement, CaseStatements, SpanFrom(CaseStatement, EndBlockStatement), null)); } else { Span span2 = CaseStatement.Span; List Comments2 = null; StatementCollection CaseStatements = ParseStatementBlock(span2, TreeType.CaseElseBlockStatement, ref Comments2, ref EndBlockStatement); CaseElseBlockStatement = new CaseElseBlockStatement((CaseElseStatement)CaseStatement, CaseStatements, SpanFrom(CaseStatement, EndBlockStatement), null); } } if (CaseBlocks.Count > 0) { CaseBlockList = new StatementCollection(CaseBlocks, null, new Span(((CaseBlockStatement)CaseBlocks[0]).Span.Start, ((CaseBlockStatement)CaseBlocks[checked(CaseBlocks.Count - 1)]).Span.Finish)); } return new SelectBlockStatement(CaseLocation, SelectExpression, Statements, CaseBlockList, CaseElseBlockStatement, (EndBlockStatement)EndBlockStatement, SpanFrom(Start), Comments); } private Statement ParseElseIfStatement() { Token Start = Read(); Expression Expression = ParseExpression(); if (ErrorInConstruct) { ResyncAt(TokenType.Then); } Location ThenLocation = default(Location); if (Peek().Type == TokenType.Then) { ThenLocation = ReadLocation(); } return new ElseIfStatement(Expression, ThenLocation, SpanFrom(Start), ParseTrailingComments()); } private Statement ParseIfBlockStatement() { Token Start = Read(); Statement EndBlockStatement = null; List ElseIfBlocks = new List(); StatementCollection ElseIfBlockList = null; ElseBlockStatement ElseBlockStatement = null; List Comments = null; Expression Expression = ParseExpression(); if (ErrorInConstruct) { ResyncAt(TokenType.Then); } Location ThenLocation = default(Location); StatementCollection IfStatements; if (Peek().Type == TokenType.Then) { ThenLocation = ReadLocation(); if (!CanEndStatement(Peek())) { StatementCollection ElseStatements = null; AtBeginningOfLine = false; IfStatements = ParseLineIfStatementBlock(); Location ElseLocation = default(Location); if (Peek().Type == TokenType.Else) { ElseLocation = ReadLocation(); ElseStatements = ParseLineIfStatementBlock(); } return new LineIfStatement(Expression, ThenLocation, IfStatements, ElseLocation, ElseStatements, SpanFrom(Start), ParseTrailingComments()); } } IfStatements = ParseStatementBlock(SpanFrom(Start), TreeType.IfBlockStatement, ref Comments, ref EndBlockStatement); while (EndBlockStatement != null && EndBlockStatement.Type != TreeType.EndBlockStatement) { Statement ElseStatement = EndBlockStatement; if (ElseStatement.Type == TreeType.ElseIfStatement) { Span span = ElseStatement.Span; List Comments2 = null; StatementCollection Statements = ParseStatementBlock(span, TreeType.ElseIfBlockStatement, ref Comments2, ref EndBlockStatement); ElseIfBlocks.Add(new ElseIfBlockStatement((ElseIfStatement)ElseStatement, Statements, SpanFrom(ElseStatement, EndBlockStatement), null)); } else { Span span2 = ElseStatement.Span; List Comments2 = null; StatementCollection Statements = ParseStatementBlock(span2, TreeType.ElseBlockStatement, ref Comments2, ref EndBlockStatement); ElseBlockStatement = new ElseBlockStatement((ElseStatement)ElseStatement, Statements, SpanFrom(ElseStatement, EndBlockStatement), null); } } if (ElseIfBlocks.Count > 0) { ElseIfBlockList = new StatementCollection(ElseIfBlocks, null, new Span(ElseIfBlocks[0].Span.Start, ElseIfBlocks[checked(ElseIfBlocks.Count - 1)].Span.Finish)); } return new IfBlockStatement(Expression, ThenLocation, IfStatements, ElseIfBlockList, ElseBlockStatement, (EndBlockStatement)EndBlockStatement, SpanFrom(Start), Comments); } private Statement ParseStatement(ref Token terminator) { Token Start = Peek(); Statement Statement = null; ErrorInConstruct = false; switch (Start.Type) { case TokenType.GoTo: Statement = ParseGotoStatement(); break; case TokenType.Exit: Statement = ParseExitStatement(); break; case TokenType.Continue: Statement = ParseContinueStatement(); break; case TokenType.Stop: Statement = new StopStatement(SpanFrom(Read()), ParseTrailingComments()); break; case TokenType.End: Statement = ParseEndStatement(); break; case TokenType.Wend: Statement = ParseWendStatement(); break; case TokenType.Return: Statement = ParseExpressionStatement(TreeType.ReturnStatement, operandOptional: true); break; case TokenType.RaiseEvent: Statement = ParseRaiseEventStatement(); break; case TokenType.AddHandler: case TokenType.RemoveHandler: Statement = ParseHandlerStatement(); break; case TokenType.Error: Statement = ParseExpressionStatement(TreeType.ErrorStatement, operandOptional: false); break; case TokenType.On: Statement = ParseOnErrorStatement(); break; case TokenType.Resume: Statement = ParseResumeStatement(); break; case TokenType.ReDim: Statement = ParseReDimStatement(); break; case TokenType.Erase: Statement = ParseEraseStatement(); break; case TokenType.Call: Statement = ParseCallStatement(); break; case TokenType.IntegerLiteral: if (AtBeginningOfLine) { Statement = ParseLabelStatement(); break; } goto default; case TokenType.Set: { Read(); Expression Target2 = ParseBinaryOperatorExpression(PrecedenceLevel.Power); if (ErrorInConstruct) { ResyncAt(TokenType.Equals); } if (GetAssignmentOperator(Peek().Type) != 0) { Statement = ParseAssignmentStatement(Target2, isSetStatement: true); break; } goto default; } case TokenType.Identifier: if (AtBeginningOfLine) { Read(); bool IsLabel = Peek().Type == TokenType.Colon; Backtrack(Start); if (IsLabel) { Statement = ParseLabelStatement(); break; } } if (Start.AsUnreservedKeyword() == TokenType.Mid) { Statement = ParseMidAssignmentStatement(); } if (Statement == null) { goto case TokenType.Boolean; } break; case TokenType.Boolean: case TokenType.Byte: case TokenType.CBool: case TokenType.CByte: case TokenType.CChar: case TokenType.CDate: case TokenType.CDec: case TokenType.CDbl: case TokenType.Char: case TokenType.CInt: case TokenType.CLng: case TokenType.CObj: case TokenType.CShort: case TokenType.CSng: case TokenType.CStr: case TokenType.CType: case TokenType.Date: case TokenType.Decimal: case TokenType.DirectCast: case TokenType.Double: case TokenType.GetType: case TokenType.Integer: case TokenType.Long: case TokenType.Me: case TokenType.MyBase: case TokenType.MyClass: case TokenType.Object: case TokenType.Short: case TokenType.Single: case TokenType.String: case TokenType.Exclamation: case TokenType.Period: { Expression Target = ParseBinaryOperatorExpression(PrecedenceLevel.Power); if (ErrorInConstruct) { ResyncAt(TokenType.Equals); } Statement = ((GetAssignmentOperator(Peek().Type) == TreeType.SyntaxError) ? ParseCallStatement(Target) : ParseAssignmentStatement(Target, isSetStatement: false)); break; } case TokenType.Const: case TokenType.Default: case TokenType.Dim: case TokenType.Friend: case TokenType.MustInherit: case TokenType.MustOverride: case TokenType.Narrowing: case TokenType.NotInheritable: case TokenType.NotOverridable: case TokenType.Overloads: case TokenType.Overridable: case TokenType.Overrides: case TokenType.Partial: case TokenType.Private: case TokenType.Protected: case TokenType.Public: case TokenType.ReadOnly: case TokenType.Shadows: case TokenType.Shared: case TokenType.Static: case TokenType.Widening: case TokenType.WithEvents: case TokenType.WriteOnly: Statement = ParseLocalDeclarationStatement(); break; case TokenType.With: Statement = ParseExpressionBlockStatement(TreeType.WithBlockStatement); break; case TokenType.SyncLock: Statement = ParseExpressionBlockStatement(TreeType.SyncLockBlockStatement); break; case TokenType.Using: Statement = ParseUsingBlockStatement(); break; case TokenType.While: Statement = ParseExpressionBlockStatement(TreeType.WhileBlockStatement); break; case TokenType.Do: Statement = ParseDoBlockStatement(); break; case TokenType.Loop: Statement = ParseLoopStatement(); break; case TokenType.For: Statement = ParseForBlockStatement(); break; case TokenType.Next: Statement = ParseNextStatement(); break; case TokenType.Throw: Statement = ParseExpressionStatement(TreeType.ThrowStatement, operandOptional: true); break; case TokenType.Try: Statement = ParseTryBlockStatement(); break; case TokenType.Catch: Statement = ParseCatchStatement(); break; case TokenType.Finally: Statement = new FinallyStatement(SpanFrom(Read()), ParseTrailingComments()); break; case TokenType.Select: Statement = ParseSelectBlockStatement(); break; case TokenType.Case: Statement = ParseCaseStatement(); CanContinueWithoutLineTerminator = true; break; case TokenType.If: Statement = ParseIfBlockStatement(); break; case TokenType.Else: Statement = new ElseStatement(SpanFrom(Read()), ParseTrailingComments()); break; case TokenType.ElseIf: Statement = ParseElseIfStatement(); break; case TokenType.Comment: { List Comments = new List(); Token LastTerminator; do { CommentToken CommentToken = (CommentToken)Scanner.Read(); Comments.Add(new Comment(CommentToken.Comment, CommentToken.IsREM, CommentToken.Span)); LastTerminator = Read(); } while (Peek().Type == TokenType.Comment); Backtrack(LastTerminator); Statement = new EmptyStatement(SpanFrom(Start), new List(Comments)); break; } default: ReportSyntaxError(SyntaxErrorType.SyntaxError, Peek()); break; case TokenType.LineTerminator: case TokenType.Colon: break; } terminator = VerifyEndOfStatement(); return Statement; } private Statement ParseStatementOrDeclaration(ref Token terminator) { Token Start = Peek(); Statement Statement = null; ErrorInConstruct = false; Location StartLocation = Peek().Span.Start; switch (Start.Type) { case TokenType.GoTo: Statement = ParseGotoStatement(); break; case TokenType.Exit: Statement = ParseExitStatement(); break; case TokenType.Continue: Statement = ParseContinueStatement(); break; case TokenType.Stop: Statement = new StopStatement(SpanFrom(Read()), ParseTrailingComments()); break; case TokenType.End: Statement = ParseEndStatement(); break; case TokenType.Wend: Statement = ParseWendStatement(); break; case TokenType.Return: Statement = ParseExpressionStatement(TreeType.ReturnStatement, operandOptional: true); break; case TokenType.RaiseEvent: Statement = ParseRaiseEventStatement(); break; case TokenType.AddHandler: case TokenType.RemoveHandler: Statement = ParseHandlerStatement(); break; case TokenType.Error: Statement = ParseExpressionStatement(TreeType.ErrorStatement, operandOptional: false); break; case TokenType.On: Statement = ParseOnErrorStatement(); break; case TokenType.Resume: Statement = ParseResumeStatement(); break; case TokenType.ReDim: Statement = ParseReDimStatement(); break; case TokenType.Erase: Statement = ParseEraseStatement(); break; case TokenType.Call: Statement = ParseCallStatement(); break; case TokenType.IntegerLiteral: if (AtBeginningOfLine) { Statement = ParseLabelStatement(); break; } goto default; case TokenType.Set: { Read(); Expression Target2 = ParseBinaryOperatorExpression(PrecedenceLevel.Power); if (ErrorInConstruct) { ResyncAt(TokenType.Equals); } if (GetAssignmentOperator(Peek().Type) != 0) { Statement = ParseAssignmentStatement(Target2, isSetStatement: true); break; } goto default; } case TokenType.Identifier: if (AtBeginningOfLine) { Read(); bool IsLabel = Peek().Type == TokenType.Colon; Backtrack(Start); if (IsLabel) { Statement = ParseLabelStatement(); break; } } if (Start.AsUnreservedKeyword() == TokenType.Mid) { Statement = ParseMidAssignmentStatement(); } if (Statement == null) { goto case TokenType.Boolean; } break; case TokenType.Boolean: case TokenType.Byte: case TokenType.CBool: case TokenType.CByte: case TokenType.CChar: case TokenType.CDate: case TokenType.CDec: case TokenType.CDbl: case TokenType.Char: case TokenType.CInt: case TokenType.CLng: case TokenType.CObj: case TokenType.CShort: case TokenType.CSng: case TokenType.CStr: case TokenType.CType: case TokenType.Date: case TokenType.Decimal: case TokenType.DirectCast: case TokenType.Double: case TokenType.GetType: case TokenType.Integer: case TokenType.Long: case TokenType.Me: case TokenType.MyBase: case TokenType.MyClass: case TokenType.Object: case TokenType.Short: case TokenType.Single: case TokenType.String: case TokenType.Exclamation: case TokenType.Period: { Expression Target = ParseBinaryOperatorExpression(PrecedenceLevel.Power); if (ErrorInConstruct) { ResyncAt(TokenType.Equals); } Statement = ((GetAssignmentOperator(Peek().Type) == TreeType.SyntaxError) ? ParseCallStatement(Target) : ParseAssignmentStatement(Target, isSetStatement: false)); break; } case TokenType.Const: case TokenType.Default: case TokenType.Dim: case TokenType.Friend: case TokenType.MustInherit: case TokenType.MustOverride: case TokenType.Narrowing: case TokenType.NotInheritable: case TokenType.NotOverridable: case TokenType.Overloads: case TokenType.Overridable: case TokenType.Overrides: case TokenType.Partial: case TokenType.Private: case TokenType.Protected: case TokenType.Public: case TokenType.ReadOnly: case TokenType.Shadows: case TokenType.Shared: case TokenType.Static: case TokenType.Widening: case TokenType.WithEvents: case TokenType.WriteOnly: { Token NextToken = PeekAheadOne(); TokenType type = NextToken.Type; if (type == TokenType.Default || type == TokenType.Function || type == TokenType.Sub) { ModifierCollection Modifiers = ParseDeclarationModifierList(); Statement = ParseMethodDeclaration(StartLocation, null, null); } else { Statement = ParseLocalDeclarationStatement(); } break; } case TokenType.With: Statement = ParseExpressionBlockStatement(TreeType.WithBlockStatement); break; case TokenType.SyncLock: Statement = ParseExpressionBlockStatement(TreeType.SyncLockBlockStatement); break; case TokenType.Using: Statement = ParseUsingBlockStatement(); break; case TokenType.While: Statement = ParseExpressionBlockStatement(TreeType.WhileBlockStatement); break; case TokenType.Do: Statement = ParseDoBlockStatement(); break; case TokenType.Loop: Statement = ParseLoopStatement(); break; case TokenType.For: Statement = ParseForBlockStatement(); break; case TokenType.Next: Statement = ParseNextStatement(); break; case TokenType.Throw: Statement = ParseExpressionStatement(TreeType.ThrowStatement, operandOptional: true); break; case TokenType.Try: Statement = ParseTryBlockStatement(); break; case TokenType.Catch: Statement = ParseCatchStatement(); break; case TokenType.Finally: Statement = new FinallyStatement(SpanFrom(Read()), ParseTrailingComments()); break; case TokenType.Select: Statement = ParseSelectBlockStatement(); break; case TokenType.Case: Statement = ParseCaseStatement(); break; case TokenType.If: Statement = ParseIfBlockStatement(); break; case TokenType.Else: Statement = new ElseStatement(SpanFrom(Read()), ParseTrailingComments()); break; case TokenType.ElseIf: Statement = ParseElseIfStatement(); break; case TokenType.Function: case TokenType.Sub: Statement = ParseMethodDeclaration(StartLocation, null, null); break; case TokenType.Class: Statement = ParseTypeDeclaration(StartLocation, null, null, TreeType.ClassDeclaration); break; case TokenType.Imports: Statement = ParseImportsDeclaration(StartLocation, null, null); break; case TokenType.Option: Statement = ParseOptionDeclaration(StartLocation, null, null); break; case TokenType.Comment: { List Comments = new List(); Token LastTerminator; do { CommentToken CommentToken = (CommentToken)Scanner.Read(); Comments.Add(new Comment(CommentToken.Comment, CommentToken.IsREM, CommentToken.Span)); LastTerminator = Read(); } while (Peek().Type == TokenType.Comment); Backtrack(LastTerminator); Statement = new EmptyStatement(SpanFrom(Start), new List(Comments)); break; } default: ReportSyntaxError(SyntaxErrorType.SyntaxError, Peek()); break; case TokenType.LineTerminator: case TokenType.Colon: break; } terminator = VerifyEndOfStatement(); return Statement; } private StatementCollection ParseStatementBlock(Span blockStartSpan, TreeType blockType, ref List Comments, ref Statement endStatement) { List Statements = new List(); List ColonLocations = new List(); bool BlockTerminated = false; Debug.Assert(blockType != TreeType.LineIfBlockStatement); Comments = ParseTrailingComments(); Token Terminator = VerifyEndOfStatement(); CanContinueWithoutLineTerminator = false; if (Terminator.Type == TokenType.Colon) { if (blockType == TreeType.SubDeclaration || blockType == TreeType.FunctionDeclaration || blockType == TreeType.ConstructorDeclaration || blockType == TreeType.OperatorDeclaration || blockType == TreeType.GetAccessorDeclaration || blockType == TreeType.SetAccessorDeclaration || blockType == TreeType.AddHandlerAccessorDeclaration || blockType == TreeType.RemoveHandlerAccessorDeclaration || blockType == TreeType.RaiseEventAccessorDeclaration) { ReportSyntaxError(SyntaxErrorType.MethodBodyNotAtLineStart, Terminator.Span); } ColonLocations.Add(Terminator.Span.Start); } Token Start = Peek(); Location StatementsEnd = Start.Span.Finish; endStatement = null; PushBlockContext(blockType); while (Peek().Type != TokenType.EndOfStream) { Token PreviousTerminator = Terminator; Statement Statement = ParseStatement(ref Terminator); if (Statement != null) { if (Statement.Type >= TreeType.LoopStatement && Statement.Type <= TreeType.EndBlockStatement) { if (StatementEndsBlock(blockType, Statement)) { endStatement = Statement; Backtrack(Terminator); BlockTerminated = true; break; } bool StatementEndsOuterBlock = false; foreach (TreeType BlockContext in BlockContextStack) { if (StatementEndsBlock(BlockContext, Statement)) { StatementEndsOuterBlock = true; break; } } if (StatementEndsOuterBlock) { ReportMismatchedEndError(blockType, Statement.Span); Backtrack(PreviousTerminator); BlockTerminated = true; break; } ReportMissingBeginStatementError(blockType, Statement); } Statements.Add(Statement); } if (Terminator.Type == TokenType.Colon) { ColonLocations.Add(Terminator.Span.Start); StatementsEnd = Terminator.Span.Finish; } else { StatementsEnd = Terminator.Span.Finish; } } if (!BlockTerminated) { ReportMismatchedEndError(blockType, blockStartSpan); } PopBlockContext(); if (Statements.Count == 0 && ColonLocations.Count == 0) { return null; } return new StatementCollection(Statements, ColonLocations, new Span(Start.Span.Start, StatementsEnd)); } private StatementCollection ParseLineIfStatementBlock() { List Statements = new List(); List ColonLocations = new List(); Token Terminator = null; Token Start = Peek(); Location StatementsEnd = Start.Span.Finish; PushBlockContext(TreeType.LineIfBlockStatement); while (!CanEndStatement(Peek())) { Statement Statement2 = ParseStatement(ref Terminator); if (Statement2 != null) { if (Statement2.Type >= TreeType.LoopStatement && Statement2.Type <= TreeType.EndBlockStatement) { ReportSyntaxError(SyntaxErrorType.EndInLineIf, Statement2.Span); } Statements.Add(Statement2); } if (Terminator.Type == TokenType.Colon) { ColonLocations.Add(Terminator.Span.Start); StatementsEnd = Terminator.Span.Finish; continue; } Backtrack(Terminator); break; } if (Terminator.Type == TokenType.End) { Statement Statement = ParseStatement(ref Terminator); if (StatementEndsBlock(CurrentBlockContextType(), Statement)) { Backtrack(Terminator); } else { ReportSyntaxError(SyntaxErrorType.ExpectedEndIf, Statement.Span); } } PopBlockContext(); if (Statements.Count == 0 && ColonLocations.Count == 0) { return null; } return new StatementCollection(Statements, ColonLocations, new Span(Start.Span.Start, StatementsEnd)); } private void ValidateModifierList(ModifierCollection modifiers, ModifierTypes validTypes) { if (modifiers == null) { return; } foreach (Modifier Modifier in modifiers) { if ((validTypes & Modifier.ModifierType) == 0) { ReportSyntaxError(SyntaxErrorType.InvalidModifier, Modifier.Span); } } } private ModifierCollection ParseDeclarationModifierList() { List Modifiers = new List(); Token Start = Peek(); ModifierTypes FoundTypes = default(ModifierTypes); while (true) { ModifierTypes ModifierTypes; switch (Peek().Type) { case TokenType.Public: ModifierTypes = ModifierTypes.Public; goto IL_01f4; case TokenType.Private: ModifierTypes = ModifierTypes.Private; goto IL_01f4; case TokenType.Protected: ModifierTypes = ModifierTypes.Protected; goto IL_01f4; case TokenType.Friend: ModifierTypes = ModifierTypes.Friend; goto IL_01f4; case TokenType.Static: ModifierTypes = ModifierTypes.Static; goto IL_01f4; case TokenType.Shared: ModifierTypes = ModifierTypes.Shared; goto IL_01f4; case TokenType.Shadows: ModifierTypes = ModifierTypes.Shadows; goto IL_01f4; case TokenType.Overloads: ModifierTypes = ModifierTypes.Overloads; goto IL_01f4; case TokenType.MustInherit: ModifierTypes = ModifierTypes.MustInherit; goto IL_01f4; case TokenType.NotInheritable: ModifierTypes = ModifierTypes.NotInheritable; goto IL_01f4; case TokenType.Overrides: ModifierTypes = ModifierTypes.Overrides; goto IL_01f4; case TokenType.Overridable: ModifierTypes = ModifierTypes.Overridable; goto IL_01f4; case TokenType.NotOverridable: ModifierTypes = ModifierTypes.NotOverridable; goto IL_01f4; case TokenType.MustOverride: ModifierTypes = ModifierTypes.MustOverride; goto IL_01f4; case TokenType.Partial: ModifierTypes = ModifierTypes.Partial; goto IL_01f4; case TokenType.ReadOnly: ModifierTypes = ModifierTypes.ReadOnly; goto IL_01f4; case TokenType.WriteOnly: ModifierTypes = ModifierTypes.WriteOnly; goto IL_01f4; case TokenType.Dim: ModifierTypes = ModifierTypes.Dim; goto IL_01f4; case TokenType.Const: ModifierTypes = ModifierTypes.Const; goto IL_01f4; case TokenType.Default: ModifierTypes = ModifierTypes.Default; goto IL_01f4; case TokenType.WithEvents: ModifierTypes = ModifierTypes.WithEvents; goto IL_01f4; case TokenType.Widening: ModifierTypes = ModifierTypes.Widening; goto IL_01f4; case TokenType.Narrowing: ModifierTypes = ModifierTypes.Narrowing; goto IL_01f4; default: { if (Modifiers.Count == 0) { return null; } return new ModifierCollection(Modifiers, SpanFrom(Start)); } IL_01f4: if ((FoundTypes & ModifierTypes) != 0) { ReportSyntaxError(SyntaxErrorType.DuplicateModifier, Peek()); } else { FoundTypes |= ModifierTypes; } break; } Modifiers.Add(new Modifier(ModifierTypes, SpanFrom(Read()))); } } private ModifierCollection ParseParameterModifierList() { List Modifiers = new List(); Token Start = Peek(); ModifierTypes FoundTypes = default(ModifierTypes); while (true) { TokenType type = Peek().Type; ModifierTypes ModifierTypes; if (type <= TokenType.ByVal) { if (type != TokenType.ByRef) { if (type != TokenType.ByVal) { break; } ModifierTypes = ModifierTypes.ByVal; } else { ModifierTypes = ModifierTypes.ByRef; } } else if (type != TokenType.Optional) { if (type != TokenType.ParamArray) { break; } ModifierTypes = ModifierTypes.ParamArray; } else { ModifierTypes = ModifierTypes.Optional; } if ((FoundTypes & ModifierTypes) != 0) { ReportSyntaxError(SyntaxErrorType.DuplicateModifier, Peek()); } else { FoundTypes |= ModifierTypes; } Modifiers.Add(new Modifier(ModifierTypes, SpanFrom(Read()))); } if (Modifiers.Count == 0) { return null; } return new ModifierCollection(Modifiers, SpanFrom(Start)); } private VariableDeclarator ParseVariableDeclarator() { Token DeclarationStart = Peek(); List VariableNamesCommaLocations = new List(); List VariableNames = new List(); TypeName Type = null; ArgumentCollection NewArguments = null; Initializer Initializer = null; do { if (VariableNames.Count > 0) { VariableNamesCommaLocations.Add(ReadLocation()); } VariableName VariableName = ParseVariableName(allowExplicitArraySizes: true); if (ErrorInConstruct) { ResyncAt(TokenType.As, TokenType.Comma, TokenType.New, TokenType.Equals); } VariableNames.Add(VariableName); } while (Peek().Type == TokenType.Comma); VariableNameCollection VariableNameCollection = new VariableNameCollection(VariableNames, VariableNamesCommaLocations, SpanFrom(DeclarationStart)); Location AsLocation = default(Location); Location NewLocation = default(Location); if (Peek().Type == TokenType.As) { AsLocation = ReadLocation(); if (Peek().Type == TokenType.New) { NewLocation = ReadLocation(); Type = ParseTypeName(allowArrayType: false); NewArguments = ParseArguments(); } else { Type = ParseTypeName(allowArrayType: true); if (ErrorInConstruct) { ResyncAt(TokenType.Comma, TokenType.Equals); } } } Location EqualsLocation = default(Location); if (Peek().Type == TokenType.Equals && !NewLocation.IsValid) { EqualsLocation = ReadLocation(); Initializer = ParseInitializer(); if (ErrorInConstruct) { ResyncAt(TokenType.Comma); } } return new VariableDeclarator(VariableNameCollection, AsLocation, NewLocation, Type, NewArguments, EqualsLocation, Initializer, SpanFrom(DeclarationStart)); } private VariableDeclaratorCollection ParseVariableDeclarators() { Token Start = Peek(); List VariableDeclarators = new List(); List DeclarationsCommaLocations = new List(); do { if (VariableDeclarators.Count > 0) { DeclarationsCommaLocations.Add(ReadLocation()); } VariableDeclarators.Add(ParseVariableDeclarator()); } while (Peek().Type == TokenType.Comma); return new VariableDeclaratorCollection(VariableDeclarators, DeclarationsCommaLocations, SpanFrom(Start)); } private VariableDeclarator ParseForLoopVariableDeclarator(ref Expression controlExpression) { Token Start = Peek(); TypeName Type = null; List VariableNames = new List(); VariableName VariableName = ParseVariableName(allowExplicitArraySizes: false); VariableNames.Add(VariableName); VariableNameCollection VariableNameCollection = new VariableNameCollection(VariableNames, null, SpanFrom(Start)); if (ErrorInConstruct && PeekAheadFor(TokenType.As, TokenType.In, TokenType.Equals) == TokenType.As) { ResyncAt(TokenType.As); } Location AsLocation = default(Location); if (Peek().Type == TokenType.As) { AsLocation = ReadLocation(); Type = ParseTypeName(allowArrayType: true); } controlExpression = new SimpleNameExpression(VariableName.Name, VariableName.Span); return new VariableDeclarator(VariableNameCollection, AsLocation, default(Location), Type, null, default(Location), null, SpanFrom(Start)); } private CaseClause ParseCase() { Token Start = Peek(); if (Start.Type == TokenType.Is || IsRelationalOperator(Start.Type)) { OperatorType Operator = OperatorType.None; Location IsLocation = default(Location); if (Start.Type == TokenType.Is) { IsLocation = ReadLocation(); } if (IsRelationalOperator(Peek().Type)) { Token OperatorToken = Read(); Operator = GetBinaryOperator(OperatorToken.Type); Expression Operand = ParseExpression(); if (ErrorInConstruct) { ResyncAt(); } return new ComparisonCaseClause(IsLocation, Operator, OperatorToken.Span.Start, Operand, SpanFrom(Start)); } ReportSyntaxError(SyntaxErrorType.ExpectedRelationalOperator, Peek()); ResyncAt(); return null; } return new RangeCaseClause(ParseExpression(allowRange: true), SpanFrom(Start)); } private AttributeCollection ParseAttributeBlock(AttributeTypes attributeTypesAllowed) { Token Start = Peek(); List Attributes = new List(); List CommaLocations = new List(); if (Start.Type != TokenType.LessThan) { return null; } Read(); do { AttributeTypes AttributeTypes = AttributeTypes.Regular; Location AttributeTypeLocation = default(Location); Location ColonLocation = default(Location); if (Attributes.Count > 0) { CommaLocations.Add(ReadLocation()); } Token AttributeStart = Peek(); if (AttributeStart.AsUnreservedKeyword() == TokenType.Assembly) { AttributeTypes = AttributeTypes.Assembly; AttributeTypeLocation = ReadLocation(); ColonLocation = VerifyExpectedToken(TokenType.Colon); } else if (AttributeStart.Type == TokenType.Module) { AttributeTypes = AttributeTypes.Module; AttributeTypeLocation = ReadLocation(); ColonLocation = VerifyExpectedToken(TokenType.Colon); } if ((AttributeTypes & attributeTypesAllowed) == 0) { ReportSyntaxError(SyntaxErrorType.IncorrectAttributeType, AttributeStart); } Name Name = ParseName(AllowGlobal: true); ArgumentCollection Arguments = ParseArguments(); Attributes.Add(new Attribute(AttributeTypes, AttributeTypeLocation, ColonLocation, Name, Arguments, SpanFrom(AttributeStart))); } while (Peek().Type == TokenType.Comma); Location RightBracketLocation = VerifyExpectedToken(TokenType.GreaterThan); return new AttributeCollection(Attributes, CommaLocations, RightBracketLocation, SpanFrom(Start)); } private AttributeBlockCollection ParseAttributes(AttributeTypes attributeTypesAllowed = AttributeTypes.Regular) { Token Start = Peek(); List AttributeBlocks = new List(); while (Peek().Type == TokenType.LessThan) { AttributeBlocks.Add(ParseAttributeBlock(attributeTypesAllowed)); } if (AttributeBlocks.Count == 0) { return null; } return new AttributeBlockCollection(AttributeBlocks, SpanFrom(Start)); } private NameCollection ParseNameList(bool allowLeadingMeOrMyBase = false) { Token Start = Read(); List CommaLocations = new List(); List Names = new List(); do { if (Names.Count > 0) { CommaLocations.Add(ReadLocation()); } Names.Add(ParseNameListName(allowLeadingMeOrMyBase)); if (ErrorInConstruct) { ResyncAt(TokenType.Comma); } } while (Peek().Type == TokenType.Comma); return new NameCollection(Names, CommaLocations, SpanFrom(Start)); } private Declaration ParsePropertyDeclaration(Location startLocation, AttributeBlockCollection attributes, ModifierCollection modifiers) { TypeName ReturnType = null; AttributeBlockCollection ReturnTypeAttributes = null; NameCollection ImplementsList = null; DeclarationCollection Accessors = null; EndBlockDeclaration EndBlockDeclaration = null; bool InInterface = CurrentBlockContextType() == TreeType.InterfaceDeclaration; List Comments = null; ModifierTypes ValidModifiers = ((!InInterface) ? (ModifierTypes.AccessModifiers | ModifierTypes.Shared | ModifierTypes.Shadows | ModifierTypes.Overloads | ModifierTypes.Overrides | ModifierTypes.NotOverridable | ModifierTypes.Overridable | ModifierTypes.MustOverride | ModifierTypes.ReadOnly | ModifierTypes.WriteOnly | ModifierTypes.Default) : (ModifierTypes.Shadows | ModifierTypes.Overloads | ModifierTypes.ReadOnly | ModifierTypes.WriteOnly | ModifierTypes.Default)); ValidateModifierList(modifiers, ValidModifiers); Location PropertyLocation = ReadLocation(); SimpleName Name = ParseSimpleName(allowKeyword: false); if (ErrorInConstruct) { ResyncAt(TokenType.LeftParenthesis, TokenType.As); } TypeParameterCollection TypeParameters = ParseTypeParameters(); if (ErrorInConstruct) { ResyncAt(TokenType.LeftParenthesis, TokenType.As); } if (TypeParameters != null && TypeParameters.Count > 0) { ReportSyntaxError(SyntaxErrorType.PropertiesCantBeGeneric, TypeParameters.Span); } ParameterCollection Parameters = ParseParameters(); Location AsLocation = default(Location); if (Peek().Type == TokenType.As) { AsLocation = ReadLocation(); ReturnTypeAttributes = ParseAttributes(); ReturnType = ParseTypeName(allowArrayType: true); if (ErrorInConstruct) { ResyncAt(TokenType.Implements); } } if (InInterface) { Comments = ParseTrailingComments(); } else { if (Peek().Type == TokenType.Implements) { ImplementsList = ParseNameList(); } if (modifiers == null || (modifiers.ModifierTypes & ModifierTypes.MustOverride) == 0) { Accessors = ParseDeclarationBlock(SpanFrom(startLocation), TreeType.PropertyDeclaration, ref Comments, ref EndBlockDeclaration); } else { Comments = ParseTrailingComments(); } } return new PropertyDeclaration(attributes, modifiers, PropertyLocation, Name, Parameters, AsLocation, ReturnTypeAttributes, ReturnType, ImplementsList, Accessors, EndBlockDeclaration, SpanFrom(startLocation), Comments); } private Declaration ParseExternalDeclaration(Location startLocation, AttributeBlockCollection attributes, ModifierCollection modifiers) { Charset Charset = Charset.Auto; TreeType MethodType = TreeType.SyntaxError; StringLiteralExpression LibLiteral = null; StringLiteralExpression AliasLiteral = null; TypeName ReturnType = null; AttributeBlockCollection ReturnTypeAttributes = null; ValidateModifierList(modifiers, ModifierTypes.AccessModifiers | ModifierTypes.Shadows | ModifierTypes.Overloads); Location DeclareLocation = ReadLocation(); Location CharsetLocation = default(Location); switch (Peek().AsUnreservedKeyword()) { case TokenType.Ansi: Charset = Charset.Ansi; CharsetLocation = ReadLocation(); break; case TokenType.Unicode: Charset = Charset.Unicode; CharsetLocation = ReadLocation(); break; case TokenType.Auto: Charset = Charset.Auto; CharsetLocation = ReadLocation(); break; } Location SubOrFunctionLocation = default(Location); if (Peek().Type == TokenType.Sub) { MethodType = TreeType.ExternalSubDeclaration; SubOrFunctionLocation = ReadLocation(); } else if (Peek().Type == TokenType.Function) { MethodType = TreeType.ExternalFunctionDeclaration; SubOrFunctionLocation = ReadLocation(); } else { ReportSyntaxError(SyntaxErrorType.ExpectedSubOrFunction, Peek()); } SimpleName Name = ParseSimpleName(allowKeyword: false); if (ErrorInConstruct) { ResyncAt(TokenType.Lib, TokenType.LeftParenthesis); } Location LibLocation = default(Location); if (Peek().Type == TokenType.Lib) { LibLocation = ReadLocation(); if (Peek().Type == TokenType.StringLiteral) { StringLiteralToken Literal2 = (StringLiteralToken)Read(); LibLiteral = new StringLiteralExpression(Literal2.Literal, Literal2.Span); } else { ReportSyntaxError(SyntaxErrorType.ExpectedStringLiteral, Peek()); ResyncAt(TokenType.Alias, TokenType.LeftParenthesis); } } else { ReportSyntaxError(SyntaxErrorType.ExpectedLib, Peek()); } Location AliasLocation = default(Location); if (Peek().Type == TokenType.Alias) { AliasLocation = ReadLocation(); if (Peek().Type == TokenType.StringLiteral) { StringLiteralToken Literal = (StringLiteralToken)Read(); AliasLiteral = new StringLiteralExpression(Literal.Literal, Literal.Span); } else { ReportSyntaxError(SyntaxErrorType.ExpectedStringLiteral, Peek()); ResyncAt(TokenType.LeftParenthesis); } } ParameterCollection Parameters = ParseParameters(); switch (MethodType) { case TreeType.ExternalFunctionDeclaration: { Location AsLocation = default(Location); if (Peek().Type == TokenType.As) { AsLocation = ReadLocation(); ReturnTypeAttributes = ParseAttributes(); ReturnType = ParseTypeName(allowArrayType: true); if (ErrorInConstruct) { ResyncAt(); } } return new ExternalFunctionDeclaration(attributes, modifiers, DeclareLocation, CharsetLocation, Charset, SubOrFunctionLocation, Name, LibLocation, LibLiteral, AliasLocation, AliasLiteral, Parameters, AsLocation, ReturnTypeAttributes, ReturnType, SpanFrom(startLocation), ParseTrailingComments()); } case TreeType.ExternalSubDeclaration: return new ExternalSubDeclaration(attributes, modifiers, DeclareLocation, CharsetLocation, Charset, SubOrFunctionLocation, Name, LibLocation, LibLiteral, AliasLocation, AliasLiteral, Parameters, SpanFrom(startLocation), ParseTrailingComments()); default: return Declaration.GetBadDeclaration(SpanFrom(startLocation), ParseTrailingComments()); } } private Declaration ParseMethodDeclaration(Location startLocation, AttributeBlockCollection attributes, ModifierCollection modifiers) { TypeName ReturnType = null; AttributeBlockCollection ReturnTypeAttributes = null; NameCollection ImplementsList = null; NameCollection HandlesList = null; bool AllowKeywordsForName = false; ModifierTypes ValidModifiers = ModifierTypes.AccessModifiers | ModifierTypes.Shared | ModifierTypes.Shadows | ModifierTypes.Overloads | ModifierTypes.Overrides | ModifierTypes.NotOverridable | ModifierTypes.Overridable | ModifierTypes.MustOverride; StatementCollection Statements = null; Statement EndStatement = null; EndBlockDeclaration EndDeclaration = null; bool InInterface = CurrentBlockContextType() == TreeType.InterfaceDeclaration; List Comments = null; TypeParameterCollection TypeParameters = null; if (!AtBeginningOfLine) { ReportSyntaxError(SyntaxErrorType.MethodMustBeFirstStatementOnLine, Peek()); } Location SubOrFunctionLocation; TreeType MethodType; if (Peek().Type == TokenType.Sub) { SubOrFunctionLocation = ReadLocation(); if (Peek().Type == TokenType.New) { MethodType = TreeType.ConstructorDeclaration; AllowKeywordsForName = true; ValidModifiers = ModifierTypes.AccessModifiers | ModifierTypes.Shared; } else { MethodType = TreeType.SubDeclaration; } } else { SubOrFunctionLocation = ReadLocation(); MethodType = TreeType.FunctionDeclaration; } if (InInterface) { ValidModifiers = ModifierTypes.Shadows | ModifierTypes.Overloads; } ValidateModifierList(modifiers, ValidModifiers); SimpleName Name = ParseSimpleName(AllowKeywordsForName); if (ErrorInConstruct) { ResyncAt(TokenType.LeftParenthesis, TokenType.As); } TypeParameters = ParseTypeParameters(); if (ErrorInConstruct) { ResyncAt(TokenType.LeftParenthesis, TokenType.As); } if (MethodType == TreeType.ConstructorDeclaration && TypeParameters != null && TypeParameters.Count > 0) { ReportSyntaxError(SyntaxErrorType.ConstructorsCantBeGeneric, TypeParameters.Span); } ParameterCollection Parameters = ParseParameters(); Location AsLocation = default(Location); if (MethodType == TreeType.FunctionDeclaration && Peek().Type == TokenType.As) { AsLocation = ReadLocation(); ReturnTypeAttributes = ParseAttributes(); ReturnType = ParseTypeName(allowArrayType: true); if (ErrorInConstruct) { ResyncAt(TokenType.Implements, TokenType.Handles); } } if (InInterface) { Comments = ParseTrailingComments(); } else { if (Peek().Type == TokenType.Implements) { ImplementsList = ParseNameList(); } else if (Peek().Type == TokenType.Handles) { HandlesList = ParseNameList(allowLeadingMeOrMyBase: true); } if (modifiers == null || (modifiers.ModifierTypes & ModifierTypes.MustOverride) == 0) { Statements = ParseStatementBlock(SpanFrom(startLocation), MethodType, ref Comments, ref EndStatement); } else { Comments = ParseTrailingComments(); } if (EndStatement != null) { EndDeclaration = new EndBlockDeclaration((EndBlockStatement)EndStatement); } } return MethodType switch { TreeType.SubDeclaration => new SubDeclaration(attributes, modifiers, SubOrFunctionLocation, Name, TypeParameters, Parameters, ImplementsList, HandlesList, Statements, EndDeclaration, SpanFrom(startLocation), Comments), TreeType.FunctionDeclaration => new FunctionDeclaration(attributes, modifiers, SubOrFunctionLocation, Name, TypeParameters, Parameters, AsLocation, ReturnTypeAttributes, ReturnType, ImplementsList, HandlesList, Statements, EndDeclaration, SpanFrom(startLocation), Comments), _ => new ConstructorDeclaration(attributes, modifiers, SubOrFunctionLocation, Name, Parameters, Statements, EndDeclaration, SpanFrom(startLocation), Comments), }; } private Declaration ParseOperatorDeclaration(Location startLocation, AttributeBlockCollection attributes, ModifierCollection modifiers) { Token OperatorToken = null; TypeName ReturnType = null; AttributeBlockCollection ReturnTypeAttributes = null; ModifierTypes ValidModifiers = ModifierTypes.Public | ModifierTypes.Shared | ModifierTypes.Shadows | ModifierTypes.Overloads | ModifierTypes.Widening | ModifierTypes.Narrowing; StatementCollection Statements = null; Statement EndStatement = null; EndBlockDeclaration EndDeclaration = null; List Comments = null; if (!AtBeginningOfLine) { ReportSyntaxError(SyntaxErrorType.MethodMustBeFirstStatementOnLine, Peek()); } Location KeywordLocation = ReadLocation(); ValidateModifierList(modifiers, ValidModifiers); if (IsOverloadableOperator(Peek())) { OperatorToken = Read(); } else { ReportSyntaxError(SyntaxErrorType.InvalidOperator, Peek()); ResyncAt(TokenType.LeftParenthesis, TokenType.As); } TypeParameterCollection TypeParameters = ParseTypeParameters(); if (ErrorInConstruct) { ResyncAt(TokenType.LeftParenthesis, TokenType.As); } if (TypeParameters != null && TypeParameters.Count > 0) { ReportSyntaxError(SyntaxErrorType.OperatorsCantBeGeneric, TypeParameters.Span); } ParameterCollection Parameters = ParseParameters(); Location AsLocation = default(Location); if (Peek().Type == TokenType.As) { AsLocation = ReadLocation(); ReturnTypeAttributes = ParseAttributes(); ReturnType = ParseTypeName(allowArrayType: true); if (ErrorInConstruct) { ResyncAt(); } } Statements = ParseStatementBlock(SpanFrom(startLocation), TreeType.OperatorDeclaration, ref Comments, ref EndStatement); Comments = ParseTrailingComments(); if (EndStatement != null) { EndDeclaration = new EndBlockDeclaration((EndBlockStatement)EndStatement); } return new OperatorDeclaration(attributes, modifiers, KeywordLocation, OperatorToken, Parameters, AsLocation, ReturnTypeAttributes, ReturnType, Statements, EndDeclaration, SpanFrom(startLocation), Comments); } private Declaration ParseAccessorDeclaration(Location startLocation, AttributeBlockCollection attributes, ModifierCollection modifiers) { ParameterCollection Parameters = null; Statement EndStatement = null; EndBlockDeclaration EndDeclaration = null; List Comments = null; ModifierTypes ValidModifiers = ModifierTypes.None; if (Scanner.Version > LanguageVersion.VisualBasic71) { ValidModifiers |= ModifierTypes.AccessModifiers; } if (!AtBeginningOfLine) { ReportSyntaxError(SyntaxErrorType.MethodMustBeFirstStatementOnLine, Peek()); } ValidateModifierList(modifiers, ValidModifiers); TreeType AccessorType = ((Peek().Type != TokenType.Get) ? TreeType.SetAccessorDeclaration : TreeType.GetAccessorDeclaration); Location GetOrSetLocation = ReadLocation(); if (AccessorType == TreeType.SetAccessorDeclaration) { Parameters = ParseParameters(); } StatementCollection Statements = ParseStatementBlock(SpanFrom(startLocation), AccessorType, ref Comments, ref EndStatement); if (EndStatement != null) { EndDeclaration = new EndBlockDeclaration((EndBlockStatement)EndStatement); } if (AccessorType == TreeType.GetAccessorDeclaration) { return new GetAccessorDeclaration(attributes, modifiers, GetOrSetLocation, Statements, EndDeclaration, SpanFrom(startLocation), Comments); } return new SetAccessorDeclaration(attributes, modifiers, GetOrSetLocation, Parameters, Statements, EndDeclaration, SpanFrom(startLocation), Comments); } private Declaration ParseCustomEventDeclaration(Location startLocation, AttributeBlockCollection attributes, ModifierCollection modifiers) { NameCollection ImplementsList = null; DeclarationCollection Accessors = null; EndBlockDeclaration EndBlockDeclaration = null; List Comments = null; ValidateModifierList(modifiers, ModifierTypes.AccessModifiers | ModifierTypes.Shared | ModifierTypes.Shadows); Location CustomLocation = ReadLocation(); Debug.Assert(Peek().Type == TokenType.Event); Location EventLocation = ReadLocation(); SimpleName Name = ParseSimpleName(allowKeyword: false); if (ErrorInConstruct) { ResyncAt(TokenType.As); } Location AsLocation = VerifyExpectedToken(TokenType.As); TypeName EventType = ParseTypeName(allowArrayType: true); if (ErrorInConstruct) { ResyncAt(TokenType.Implements); } if (Peek().Type == TokenType.Implements) { ImplementsList = ParseNameList(); } Accessors = ParseDeclarationBlock(SpanFrom(startLocation), TreeType.CustomEventDeclaration, ref Comments, ref EndBlockDeclaration); return new CustomEventDeclaration(attributes, modifiers, CustomLocation, EventLocation, Name, AsLocation, EventType, ImplementsList, Accessors, EndBlockDeclaration, SpanFrom(startLocation), Comments); } private Declaration ParseEventAccessorDeclaration(Location startLocation, AttributeBlockCollection attributes, ModifierCollection modifiers) { ParameterCollection Parameters = null; Statement EndStatement = null; EndBlockDeclaration EndDeclaration = null; List Comments = null; if (!AtBeginningOfLine) { ReportSyntaxError(SyntaxErrorType.MethodMustBeFirstStatementOnLine, Peek()); } ValidateModifierList(modifiers, ModifierTypes.None); TreeType AccessorType = ((Peek().Type == TokenType.AddHandler) ? TreeType.AddHandlerAccessorDeclaration : ((Peek().Type != TokenType.RemoveHandler) ? TreeType.RaiseEventAccessorDeclaration : TreeType.RemoveHandlerAccessorDeclaration)); Location AccessorTypeLocation = ReadLocation(); Parameters = ParseParameters(); StatementCollection Statements = ParseStatementBlock(SpanFrom(startLocation), AccessorType, ref Comments, ref EndStatement); if (EndStatement != null) { EndDeclaration = new EndBlockDeclaration((EndBlockStatement)EndStatement); } return AccessorType switch { TreeType.AddHandlerAccessorDeclaration => new AddHandlerAccessorDeclaration(attributes, AccessorTypeLocation, Parameters, Statements, EndDeclaration, SpanFrom(startLocation), Comments), TreeType.RemoveHandlerAccessorDeclaration => new RemoveHandlerAccessorDeclaration(attributes, AccessorTypeLocation, Parameters, Statements, EndDeclaration, SpanFrom(startLocation), Comments), _ => new RaiseEventAccessorDeclaration(attributes, AccessorTypeLocation, Parameters, Statements, EndDeclaration, SpanFrom(startLocation), Comments), }; } private Declaration ParseEventDeclaration(Location startLocation, AttributeBlockCollection attributes, ModifierCollection modifiers) { TypeName EventType = null; ParameterCollection Parameters = null; NameCollection ImplementsList = null; ModifierTypes ValidModifiers = ((CurrentBlockContextType() != TreeType.InterfaceDeclaration) ? (ModifierTypes.AccessModifiers | ModifierTypes.Shared | ModifierTypes.Shadows) : ModifierTypes.Shadows); ValidateModifierList(modifiers, ValidModifiers); Location EventLocation = ReadLocation(); SimpleName Name = ParseSimpleName(allowKeyword: false); if (ErrorInConstruct) { ResyncAt(TokenType.As, TokenType.LeftParenthesis, TokenType.Implements); } Location AsLocation = default(Location); if (Peek().Type == TokenType.As) { AsLocation = ReadLocation(); EventType = ParseTypeName(allowArrayType: false); if (ErrorInConstruct) { ResyncAt(TokenType.Implements); } } else { Parameters = ParseParameters(); if (Peek().Type == TokenType.As) { Token ErrorStart = Peek(); ResyncAt(TokenType.Implements); ReportSyntaxError(SyntaxErrorType.EventsCantBeFunctions, ErrorStart, Peek()); } } if (Peek().Type == TokenType.Implements) { ImplementsList = ParseNameList(); } return new EventDeclaration(attributes, modifiers, EventLocation, Name, Parameters, AsLocation, null, EventType, ImplementsList, SpanFrom(startLocation), ParseTrailingComments()); } private Declaration ParseVariableListDeclaration(Location startLocation, AttributeBlockCollection attributes, ModifierCollection modifiers) { ModifierTypes ValidModifiers = ((modifiers == null || (modifiers.ModifierTypes & ModifierTypes.Const) == 0) ? (ModifierTypes.AccessModifiers | ModifierTypes.Shared | ModifierTypes.Shadows | ModifierTypes.ReadOnly | ModifierTypes.Dim | ModifierTypes.WithEvents) : (ModifierTypes.AccessModifiers | ModifierTypes.Shadows | ModifierTypes.Const)); ValidateModifierList(modifiers, ValidModifiers); if (modifiers == null) { ReportSyntaxError(SyntaxErrorType.ExpectedModifier, Peek()); } return new VariableListDeclaration(attributes, modifiers, ParseVariableDeclarators(), SpanFrom(startLocation), ParseTrailingComments()); } private Declaration ParseEndDeclaration() { Token Start = Read(); BlockType EndType = GetBlockType(Peek().Type); switch (EndType) { case BlockType.Sub: if (!AtBeginningOfLine) { ReportSyntaxError(SyntaxErrorType.EndSubNotAtLineStart, SpanFrom(Start)); } break; case BlockType.Function: if (!AtBeginningOfLine) { ReportSyntaxError(SyntaxErrorType.EndFunctionNotAtLineStart, SpanFrom(Start)); } break; case BlockType.Operator: if (!AtBeginningOfLine) { ReportSyntaxError(SyntaxErrorType.EndOperatorNotAtLineStart, SpanFrom(Start)); } break; case BlockType.Get: if (!AtBeginningOfLine) { ReportSyntaxError(SyntaxErrorType.EndGetNotAtLineStart, SpanFrom(Start)); } break; case BlockType.Set: if (!AtBeginningOfLine) { ReportSyntaxError(SyntaxErrorType.EndSetNotAtLineStart, SpanFrom(Start)); } break; case BlockType.AddHandler: if (!AtBeginningOfLine) { ReportSyntaxError(SyntaxErrorType.EndAddHandlerNotAtLineStart, SpanFrom(Start)); } break; case BlockType.RemoveHandler: if (!AtBeginningOfLine) { ReportSyntaxError(SyntaxErrorType.EndRemoveHandlerNotAtLineStart, SpanFrom(Start)); } break; case BlockType.RaiseEvent: if (!AtBeginningOfLine) { ReportSyntaxError(SyntaxErrorType.EndRaiseEventNotAtLineStart, SpanFrom(Start)); } break; case BlockType.None: ReportSyntaxError(SyntaxErrorType.UnrecognizedEnd, Peek()); return Declaration.GetBadDeclaration(SpanFrom(Start), ParseTrailingComments()); } return new EndBlockDeclaration(EndType, ReadLocation(), SpanFrom(Start), ParseTrailingComments()); } private Declaration ParseTypeDeclaration(Location startLocation, AttributeBlockCollection attributes, ModifierCollection modifiers, TreeType blockType) { EndBlockDeclaration EndBlockDeclaration = null; List Comments = null; TypeParameterCollection TypeParameters = null; ModifierTypes ValidModifiers; if (blockType == TreeType.ModuleDeclaration) { ValidModifiers = ModifierTypes.AccessModifiers; } else { ValidModifiers = ModifierTypes.AccessModifiers | ModifierTypes.Shadows; if (blockType == TreeType.ClassDeclaration) { ValidModifiers = ValidModifiers | ModifierTypes.MustInherit | ModifierTypes.NotInheritable; } if (blockType == TreeType.ClassDeclaration || blockType == TreeType.StructureDeclaration) { ValidModifiers |= ModifierTypes.Partial; } } ValidateModifierList(modifiers, ValidModifiers); Location KeywordLocation = ReadLocation(); SimpleName Name = ParseSimpleName(allowKeyword: false); if (ErrorInConstruct) { ResyncAt(); } TypeParameters = ParseTypeParameters(); if (ErrorInConstruct) { ResyncAt(); } if (blockType == TreeType.ModuleDeclaration && TypeParameters != null && TypeParameters.Count > 0) { ReportSyntaxError(SyntaxErrorType.ModulesCantBeGeneric, TypeParameters.Span); } DeclarationCollection Members = ParseDeclarationBlock(SpanFrom(startLocation), blockType, ref Comments, ref EndBlockDeclaration); switch (blockType) { case TreeType.ClassDeclaration: return new ClassDeclaration(attributes, modifiers, KeywordLocation, Name, TypeParameters, Members, EndBlockDeclaration, SpanFrom(startLocation), Comments); case TreeType.ModuleDeclaration: return new ModuleDeclaration(attributes, modifiers, KeywordLocation, Name, Members, EndBlockDeclaration, SpanFrom(startLocation), Comments); case TreeType.InterfaceDeclaration: return new InterfaceDeclaration(attributes, modifiers, KeywordLocation, Name, TypeParameters, Members, EndBlockDeclaration, SpanFrom(startLocation), Comments); case TreeType.StructureDeclaration: return new StructureDeclaration(attributes, modifiers, KeywordLocation, Name, TypeParameters, Members, EndBlockDeclaration, SpanFrom(startLocation), Comments); default: Debug.Assert(condition: false, "unexpected!"); return null; } } private Declaration ParseEnumDeclaration(Location startLocation, AttributeBlockCollection attributes, ModifierCollection modifiers) { TypeName Type = null; EndBlockDeclaration EndBlockDeclaration = null; List Comments = null; ValidateModifierList(modifiers, ModifierTypes.AccessModifiers | ModifierTypes.Shadows); Location KeywordLocation = ReadLocation(); SimpleName Name = ParseSimpleName(allowKeyword: false); if (ErrorInConstruct) { ResyncAt(TokenType.As); } Location AsLocation = default(Location); if (Peek().Type == TokenType.As) { AsLocation = ReadLocation(); Type = ParseTypeName(allowArrayType: false); if (ErrorInConstruct) { ResyncAt(); } } DeclarationCollection Members = ParseDeclarationBlock(SpanFrom(startLocation), TreeType.EnumDeclaration, ref Comments, ref EndBlockDeclaration); if (Members == null || Members.Count == 0) { ReportSyntaxError(SyntaxErrorType.EmptyEnum, Name.Span); } return new EnumDeclaration(attributes, modifiers, KeywordLocation, Name, AsLocation, Type, Members, EndBlockDeclaration, SpanFrom(startLocation), Comments); } private Declaration ParseDelegateDeclaration(Location startLocation, AttributeBlockCollection attributes, ModifierCollection modifiers) { TreeType MethodType = TreeType.SyntaxError; TypeName ReturnType = null; AttributeBlockCollection ReturnTypeAttributes = null; TypeParameterCollection TypeParameters = null; ValidateModifierList(modifiers, ModifierTypes.AccessModifiers | ModifierTypes.Shared | ModifierTypes.Shadows); Location DelegateLocation = ReadLocation(); Location SubOrFunctionLocation = default(Location); if (Peek().Type == TokenType.Sub) { SubOrFunctionLocation = ReadLocation(); MethodType = TreeType.SubDeclaration; } else if (Peek().Type == TokenType.Function) { SubOrFunctionLocation = ReadLocation(); MethodType = TreeType.FunctionDeclaration; } else { ReportSyntaxError(SyntaxErrorType.ExpectedSubOrFunction, Peek()); MethodType = TreeType.SubDeclaration; } SimpleName Name = ParseSimpleName(allowKeyword: false); if (ErrorInConstruct) { ResyncAt(TokenType.LeftParenthesis, TokenType.As); } TypeParameters = ParseTypeParameters(); if (ErrorInConstruct) { ResyncAt(TokenType.LeftParenthesis, TokenType.As); } ParameterCollection Parameters = ParseParameters(); Location AsLocation = default(Location); if (MethodType == TreeType.FunctionDeclaration && Peek().Type == TokenType.As) { AsLocation = ReadLocation(); ReturnTypeAttributes = ParseAttributes(); ReturnType = ParseTypeName(allowArrayType: true); if (ErrorInConstruct) { ResyncAt(); } } if (MethodType == TreeType.SubDeclaration) { return new DelegateSubDeclaration(attributes, modifiers, DelegateLocation, SubOrFunctionLocation, Name, TypeParameters, Parameters, SpanFrom(startLocation), ParseTrailingComments()); } return new DelegateFunctionDeclaration(attributes, modifiers, DelegateLocation, SubOrFunctionLocation, Name, TypeParameters, Parameters, AsLocation, ReturnTypeAttributes, ReturnType, SpanFrom(startLocation), ParseTrailingComments()); } private Declaration ParseTypeListDeclaration(Location startLocation, AttributeBlockCollection attributes, ModifierCollection modifiers, TreeType listType) { List CommaLocations = new List(); List Types = new List(); Read(); if (attributes != null) { ReportSyntaxError(SyntaxErrorType.SpecifiersInvalidOnTypeListDeclaration, attributes.Span); } if (modifiers != null) { ReportSyntaxError(SyntaxErrorType.SpecifiersInvalidOnTypeListDeclaration, modifiers.Span); } Token ListStart = Peek(); do { if (Types.Count > 0) { CommaLocations.Add(ReadLocation()); } Types.Add(ParseTypeName(allowArrayType: false)); if (ErrorInConstruct) { ResyncAt(TokenType.Comma); } } while (Peek().Type == TokenType.Comma); if (listType == TreeType.InheritsDeclaration) { return new InheritsDeclaration(new TypeNameCollection(Types, CommaLocations, SpanFrom(ListStart)), SpanFrom(startLocation), ParseTrailingComments()); } return new ImplementsDeclaration(new TypeNameCollection(Types, CommaLocations, SpanFrom(ListStart)), SpanFrom(startLocation), ParseTrailingComments()); } private Declaration ParseNamespaceDeclaration(Location startLocation, AttributeBlockCollection attributes, ModifierCollection modifiers) { EndBlockDeclaration EndBlockDeclaration = null; List Comments = null; if (attributes != null) { ReportSyntaxError(SyntaxErrorType.SpecifiersInvalidOnNamespaceDeclaration, attributes.Span); } if (modifiers != null) { ReportSyntaxError(SyntaxErrorType.SpecifiersInvalidOnNamespaceDeclaration, modifiers.Span); } Location KeywordLocation = ReadLocation(); Name Name = ParseName(AllowGlobal: false); if (ErrorInConstruct) { ResyncAt(); } DeclarationCollection Members = ParseDeclarationBlock(SpanFrom(startLocation), TreeType.NamespaceDeclaration, ref Comments, ref EndBlockDeclaration); return new NamespaceDeclaration(attributes, modifiers, KeywordLocation, Name, Members, EndBlockDeclaration, SpanFrom(startLocation), Comments); } private Declaration ParseImportsDeclaration(Location startLocation, AttributeBlockCollection attributes, ModifierCollection modifiers) { List ImportMembers = new List(); List CommaLocations = new List(); if (attributes != null) { ReportSyntaxError(SyntaxErrorType.SpecifiersInvalidOnImportsDeclaration, attributes.Span); } if (modifiers != null) { ReportSyntaxError(SyntaxErrorType.SpecifiersInvalidOnImportsDeclaration, modifiers.Span); } Read(); Token ListStart = Peek(); do { if (ImportMembers.Count > 0) { CommaLocations.Add(ReadLocation()); } if (PeekAheadFor(TokenType.Equals, TokenType.Comma, TokenType.Period) == TokenType.Equals) { Token ImportStart2 = Peek(); SimpleName Name = ParseSimpleName(allowKeyword: false); Location EqualsLocation = ReadLocation(); TypeName AliasedTypeName = ParseNamedTypeName(allowGlobal: false); if (ErrorInConstruct) { ResyncAt(); } ImportMembers.Add(new AliasImport(Name, EqualsLocation, AliasedTypeName, SpanFrom(ImportStart2))); } else { Token ImportStart = Peek(); TypeName TypeName = ParseNamedTypeName(allowGlobal: false); if (ErrorInConstruct) { ResyncAt(); } ImportMembers.Add(new NameImport(TypeName, SpanFrom(ImportStart))); } } while (Peek().Type == TokenType.Comma); return new ImportsDeclaration(new ImportCollection(ImportMembers, CommaLocations, SpanFrom(ListStart)), SpanFrom(startLocation), ParseTrailingComments()); } private Declaration ParseOptionDeclaration(Location startLocation, AttributeBlockCollection attributes, ModifierCollection modifiers) { Read(); if (attributes != null) { ReportSyntaxError(SyntaxErrorType.SpecifiersInvalidOnOptionDeclaration, attributes.Span); } if (modifiers != null) { ReportSyntaxError(SyntaxErrorType.SpecifiersInvalidOnOptionDeclaration, modifiers.Span); } Location OptionTypeLocation = default(Location); Location OptionArgumentLocation = default(Location); OptionType OptionType; if (Peek().AsUnreservedKeyword() == TokenType.Explicit) { OptionTypeLocation = ReadLocation(); if (Peek().AsUnreservedKeyword() == TokenType.Off) { OptionArgumentLocation = ReadLocation(); OptionType = OptionType.ExplicitOff; } else if (Peek().Type == TokenType.On) { OptionArgumentLocation = ReadLocation(); OptionType = OptionType.ExplicitOn; } else if (Peek().Type == TokenType.Identifier) { OptionType = OptionType.SyntaxError; ReportSyntaxError(SyntaxErrorType.InvalidOptionExplicitType, SpanFrom(startLocation)); } else { OptionType = OptionType.Explicit; } } else if (Peek().AsUnreservedKeyword() == TokenType.Strict) { OptionTypeLocation = ReadLocation(); if (Peek().AsUnreservedKeyword() == TokenType.Off) { OptionArgumentLocation = ReadLocation(); OptionType = OptionType.StrictOff; } else if (Peek().Type == TokenType.On) { OptionArgumentLocation = ReadLocation(); OptionType = OptionType.StrictOn; } else if (Peek().Type == TokenType.Identifier) { OptionType = OptionType.SyntaxError; ReportSyntaxError(SyntaxErrorType.InvalidOptionStrictType, SpanFrom(startLocation)); } else { OptionType = OptionType.Strict; } } else if (Peek().AsUnreservedKeyword() == TokenType.Compare) { OptionTypeLocation = ReadLocation(); if (Peek().AsUnreservedKeyword() == TokenType.Binary) { OptionArgumentLocation = ReadLocation(); OptionType = OptionType.CompareBinary; } else if (Peek().AsUnreservedKeyword() == TokenType.Text) { OptionArgumentLocation = ReadLocation(); OptionType = OptionType.CompareText; } else { OptionType = OptionType.SyntaxError; ReportSyntaxError(SyntaxErrorType.InvalidOptionCompareType, SpanFrom(startLocation)); } } else { OptionType = OptionType.SyntaxError; ReportSyntaxError(SyntaxErrorType.InvalidOptionType, SpanFrom(startLocation)); } if (ErrorInConstruct) { ResyncAt(); } return new OptionDeclaration(OptionType, OptionTypeLocation, OptionArgumentLocation, SpanFrom(startLocation), ParseTrailingComments()); } private Declaration ParseAttributeDeclaration() { AttributeBlockCollection Attributes = ParseAttributes(AttributeTypes.Module | AttributeTypes.Assembly); return new AttributeDeclaration(Attributes, Attributes.Span, ParseTrailingComments()); } private Declaration ParseDeclaration(ref Token terminator) { Declaration Declaration = null; AttributeBlockCollection Attributes = null; ModifierCollection Modifiers = null; TokenType LookAhead = TokenType.None; Token Start = Peek(); ErrorInConstruct = false; Location StartLocation = Peek().Span.Start; LookAhead = PeekAheadFor(TokenType.Assembly, TokenType.Module, TokenType.GreaterThan); if (Peek().Type != TokenType.LessThan || (LookAhead != TokenType.Assembly && LookAhead != TokenType.Module)) { Attributes = ParseAttributes(); Modifiers = ParseDeclarationModifierList(); } switch (Peek().Type) { case TokenType.End: if (Attributes == null && Modifiers == null) { Declaration = ParseEndDeclaration(); break; } goto case TokenType.Identifier; case TokenType.Property: Declaration = ParsePropertyDeclaration(StartLocation, Attributes, Modifiers); break; case TokenType.Declare: Declaration = ParseExternalDeclaration(StartLocation, Attributes, Modifiers); break; case TokenType.Function: case TokenType.Sub: Declaration = ParseMethodDeclaration(StartLocation, Attributes, Modifiers); break; case TokenType.Get: case TokenType.Set: Declaration = ParseAccessorDeclaration(StartLocation, Attributes, Modifiers); break; case TokenType.AddHandler: case TokenType.RaiseEvent: case TokenType.RemoveHandler: Declaration = ParseEventAccessorDeclaration(StartLocation, Attributes, Modifiers); break; case TokenType.Event: Declaration = ParseEventDeclaration(StartLocation, Attributes, Modifiers); break; case TokenType.Operator: Declaration = ParseOperatorDeclaration(StartLocation, Attributes, Modifiers); break; case TokenType.Delegate: Declaration = ParseDelegateDeclaration(StartLocation, Attributes, Modifiers); break; case TokenType.Class: Declaration = ParseTypeDeclaration(StartLocation, Attributes, Modifiers, TreeType.ClassDeclaration); break; case TokenType.Structure: Declaration = ParseTypeDeclaration(StartLocation, Attributes, Modifiers, TreeType.StructureDeclaration); break; case TokenType.Module: Declaration = ParseTypeDeclaration(StartLocation, Attributes, Modifiers, TreeType.ModuleDeclaration); break; case TokenType.Interface: Declaration = ParseTypeDeclaration(StartLocation, Attributes, Modifiers, TreeType.InterfaceDeclaration); break; case TokenType.Enum: Declaration = ParseEnumDeclaration(StartLocation, Attributes, Modifiers); break; case TokenType.Namespace: Declaration = ParseNamespaceDeclaration(StartLocation, Attributes, Modifiers); break; case TokenType.Implements: Declaration = ParseTypeListDeclaration(StartLocation, Attributes, Modifiers, TreeType.ImplementsDeclaration); break; case TokenType.Inherits: Declaration = ParseTypeListDeclaration(StartLocation, Attributes, Modifiers, TreeType.InheritsDeclaration); break; case TokenType.Imports: Declaration = ParseImportsDeclaration(StartLocation, Attributes, Modifiers); break; case TokenType.Option: Declaration = ParseOptionDeclaration(StartLocation, Attributes, Modifiers); break; case TokenType.LessThan: Declaration = ParseAttributeDeclaration(); break; case TokenType.Identifier: Declaration = ((Peek().AsUnreservedKeyword() != TokenType.Custom || PeekAheadOne().Type != TokenType.Event) ? ParseVariableListDeclaration(StartLocation, Attributes, Modifiers) : ParseCustomEventDeclaration(StartLocation, Attributes, Modifiers)); break; case TokenType.EndOfStream: case TokenType.LineTerminator: case TokenType.Colon: if (Attributes != null || Modifiers != null) { ReportSyntaxError(SyntaxErrorType.ExpectedIdentifier, Peek()); } break; case TokenType.Comment: { List Comments = new List(); Token LastTerminator; do { CommentToken CommentToken = (CommentToken)Scanner.Read(); Comments.Add(new Comment(CommentToken.Comment, CommentToken.IsREM, CommentToken.Span)); LastTerminator = Read(); } while (Peek().Type == TokenType.Comment); Backtrack(LastTerminator); Declaration = new EmptyDeclaration(SpanFrom(Start), Comments); break; } default: ReportSyntaxError(SyntaxErrorType.SyntaxError, Peek()); break; } terminator = VerifyEndOfStatement(); return Declaration; } private Declaration ParseDeclarationInEnum(ref Token terminator) { Expression Expression = null; Declaration Declaration = null; Token Start = Peek(); if (Start.Type == TokenType.Comment) { List Comments = new List(); Token LastTerminator; do { CommentToken CommentToken = (CommentToken)Scanner.Read(); Comments.Add(new Comment(CommentToken.Comment, CommentToken.IsREM, CommentToken.Span)); LastTerminator = Read(); } while (Peek().Type == TokenType.Comment); Backtrack(LastTerminator); Declaration = new EmptyDeclaration(SpanFrom(Start), Comments); } else if (Start.Type != TokenType.LineTerminator && Start.Type != TokenType.Colon) { ErrorInConstruct = false; Location StartLocation = Peek().Span.Start; AttributeBlockCollection Attributes = ParseAttributes(); if (Peek().Type == TokenType.End && Attributes == null) { Declaration = ParseEndDeclaration(); } else { SimpleName Name = ParseSimpleName(allowKeyword: false); if (ErrorInConstruct) { ResyncAt(TokenType.Equals); } Location EqualsLocation = default(Location); if (Peek().Type == TokenType.Equals) { EqualsLocation = ReadLocation(); Expression = ParseExpression(); if (ErrorInConstruct) { ResyncAt(); } } Declaration = new EnumValueDeclaration(Attributes, Name, EqualsLocation, Expression, SpanFrom(StartLocation), ParseTrailingComments()); } } terminator = VerifyEndOfStatement(); return Declaration; } private DeclarationCollection ParseDeclarationBlock(Span blockStartSpan, TreeType blockType, ref List Comments, ref EndBlockDeclaration endDeclaration) { List Declarations = new List(); List ColonLocations = new List(); bool BlockTerminated = false; Comments = ParseTrailingComments(); Token Terminator = VerifyEndOfStatement(); if (Terminator.Type == TokenType.Colon) { ColonLocations.Add(Terminator.Span.Start); } Token Start = Peek(); Location DeclarationsEnd = Start.Span.Finish; endDeclaration = null; PushBlockContext(blockType); while (Peek().Type != TokenType.EndOfStream) { Token PreviousTerminator = Terminator; Declaration Declaration = ((blockType != TreeType.EnumDeclaration) ? ParseDeclaration(ref Terminator) : ParseDeclarationInEnum(ref Terminator)); if (Declaration != null) { if (Declaration.Type == TreeType.EndBlockDeclaration) { EndBlockDeclaration PotentialEndDeclaration = (EndBlockDeclaration)Declaration; if (DeclarationEndsBlock(blockType, PotentialEndDeclaration)) { endDeclaration = PotentialEndDeclaration; Backtrack(Terminator); BlockTerminated = true; break; } bool DeclarationEndsOuterBlock = false; foreach (TreeType BlockContext in BlockContextStack) { if (DeclarationEndsBlock(BlockContext, PotentialEndDeclaration)) { DeclarationEndsOuterBlock = true; break; } } if (DeclarationEndsOuterBlock) { ReportMismatchedEndError(blockType, Declaration.Span); Backtrack(PreviousTerminator); BlockTerminated = true; break; } ReportMissingBeginDeclarationError(PotentialEndDeclaration); } else { SyntaxErrorType ErrorType = ValidDeclaration(blockType, Declaration, Declarations); if (ErrorType != 0) { ReportSyntaxError(ErrorType, Declaration.Span); } } Declarations.Add(Declaration); } if (Terminator.Type == TokenType.Colon) { ColonLocations.Add(Terminator.Span.Start); } DeclarationsEnd = Terminator.Span.Finish; } if (!BlockTerminated) { ReportMismatchedEndError(blockType, blockStartSpan); } PopBlockContext(); if (Declarations.Count == 0 && ColonLocations.Count == 0) { return null; } return new DeclarationCollection(Declarations, ColonLocations, new Span(Start.Span.Start, DeclarationsEnd)); } private Parameter ParseParameter() { Token Start = Peek(); TypeName Type = null; Initializer Initializer = null; AttributeBlockCollection Attributes = ParseAttributes(); ModifierCollection Modifiers = ParseParameterModifierList(); VariableName VariableName = ParseVariableName(allowExplicitArraySizes: false); if (ErrorInConstruct && PeekAheadFor(TokenType.As, TokenType.Comma, TokenType.RightParenthesis) == TokenType.As) { ResyncAt(TokenType.As); } Location AsLocation = default(Location); if (Peek().Type == TokenType.As) { AsLocation = ReadLocation(); Type = ParseTypeName(allowArrayType: true); } if (ErrorInConstruct) { ResyncAt(TokenType.Equals, TokenType.Comma, TokenType.RightParenthesis); } Location EqualsLocation = default(Location); if (Peek().Type == TokenType.Equals) { EqualsLocation = ReadLocation(); Initializer = ParseInitializer(); } if (ErrorInConstruct) { ResyncAt(TokenType.Comma, TokenType.RightParenthesis); } return new Parameter(Attributes, Modifiers, VariableName, AsLocation, Type, EqualsLocation, Initializer, SpanFrom(Start)); } private bool ParametersContinue() { Token NextToken = Peek(); if (NextToken.Type == TokenType.Comma) { return true; } if (NextToken.Type == TokenType.RightParenthesis || MustEndStatement(NextToken)) { return false; } ReportSyntaxError(SyntaxErrorType.ParameterSyntax, NextToken); ResyncAt(TokenType.Comma, TokenType.RightParenthesis); if (Peek().Type == TokenType.Comma) { ErrorInConstruct = false; return true; } return false; } private ParameterCollection ParseParameters() { Token Start = Peek(); List Parameters = new List(); List CommaLocations = new List(); if (Start.Type != TokenType.LeftParenthesis) { return null; } Read(); if (Peek().Type != TokenType.RightParenthesis) { do { if (Parameters.Count > 0) { CommaLocations.Add(ReadLocation()); } Parameters.Add(ParseParameter()); if (ErrorInConstruct) { ResyncAt(TokenType.Comma, TokenType.RightParenthesis); } } while (ParametersContinue()); } Location RightParenthesisLocation = default(Location); if (Peek().Type == TokenType.RightParenthesis) { RightParenthesisLocation = ReadLocation(); } else { Token CurrentToken = Peek(); ResyncAt(TokenType.LeftParenthesis, TokenType.RightParenthesis); if (Peek().Type == TokenType.RightParenthesis) { ReportSyntaxError(SyntaxErrorType.SyntaxError, Peek()); RightParenthesisLocation = ReadLocation(); } else { Backtrack(CurrentToken); ReportSyntaxError(SyntaxErrorType.ExpectedRightParenthesis, Peek()); } } return new ParameterCollection(Parameters, CommaLocations, RightParenthesisLocation, SpanFrom(Start)); } private TypeConstraintCollection ParseTypeConstraints() { Token Start = Peek(); List CommaLocations = new List(); List Types = new List(); Location RightBracketLocation = default(Location); if (Peek().Type == TokenType.LeftCurlyBrace) { Read(); do { if (Types.Count > 0) { CommaLocations.Add(ReadLocation()); } Types.Add(ParseTypeName(allowArrayType: true)); if (ErrorInConstruct) { ResyncAt(TokenType.Comma); } } while (Peek().Type == TokenType.Comma); RightBracketLocation = VerifyExpectedToken(TokenType.RightCurlyBrace); } else { Types.Add(ParseTypeName(allowArrayType: true)); } return new TypeConstraintCollection(Types, CommaLocations, RightBracketLocation, SpanFrom(Start)); } private TypeParameter ParseTypeParameter() { Token Start = Peek(); TypeConstraintCollection TypeConstraints = null; SimpleName Name = ParseSimpleName(allowKeyword: false); if (ErrorInConstruct && PeekAheadFor(TokenType.As, TokenType.Comma, TokenType.RightParenthesis) == TokenType.As) { ResyncAt(TokenType.As); } Location AsLocation = default(Location); if (Peek().Type == TokenType.As) { AsLocation = ReadLocation(); TypeConstraints = ParseTypeConstraints(); } if (ErrorInConstruct) { ResyncAt(TokenType.Equals, TokenType.Comma, TokenType.RightParenthesis); } if (ErrorInConstruct) { ResyncAt(TokenType.Comma, TokenType.RightParenthesis); } return new TypeParameter(Name, AsLocation, TypeConstraints, SpanFrom(Start)); } private TypeParameterCollection ParseTypeParameters() { Token Start = Peek(); List TypeParameters = new List(); List CommaLocations = new List(); if (Start.Type != TokenType.LeftParenthesis || Scanner.Version < LanguageVersion.VisualBasic80) { return null; } Read(); if (Peek().Type != TokenType.Of || Scanner.Version < LanguageVersion.VisualBasic80) { Backtrack(Start); return null; } Location OfLocation = VerifyExpectedToken(TokenType.Of); do { if (TypeParameters.Count > 0) { CommaLocations.Add(ReadLocation()); } TypeParameters.Add(ParseTypeParameter()); if (ErrorInConstruct) { ResyncAt(TokenType.Comma, TokenType.RightParenthesis); } } while (ParametersContinue()); Location RightParenthesisLocation = VerifyExpectedToken(TokenType.RightParenthesis); return new TypeParameterCollection(OfLocation, TypeParameters, CommaLocations, RightParenthesisLocation, SpanFrom(Start)); } private File ParseFile() { List Declarations = new List(); List ColonLocations = new List(); Token Terminator = null; Token Start = Peek(); while (Peek().Type != TokenType.EndOfStream) { Declaration Declaration = ParseDeclaration(ref Terminator); if (Declaration != null) { SyntaxErrorType ErrorType = SyntaxErrorType.None; ErrorType = ValidDeclaration(TreeType.File, Declaration, Declarations); if (ErrorType != 0) { ReportSyntaxError(ErrorType, Declaration.Span); } Declarations.Add(Declaration); } if (Terminator.Type == TokenType.Colon) { ColonLocations.Add(Terminator.Span.Start); } } if (Declarations.Count == 0 && ColonLocations.Count == 0) { return new File(null, SpanFrom(Start)); } return new File(new DeclarationCollection(Declarations, ColonLocations, SpanFrom(Start)), SpanFrom(Start)); } private ScriptBlock ParseScriptFile() { List Statements = new List(); List ColonLocations = new List(); bool BlockTerminated = false; Token Start = Peek(); Location StatementsEnd = Start.Span.Finish; Token Terminator = default(Token); while (Peek().Type != TokenType.EndOfStream) { Token PreviousTerminator = Terminator; Statement Statement = ParseStatementOrDeclaration(ref Terminator); if (Statement != null) { Statements.Add(Statement); } if (Terminator.Type == TokenType.Colon) { ColonLocations.Add(Terminator.Span.Start); StatementsEnd = Terminator.Span.Finish; } else { StatementsEnd = Terminator.Span.Finish; } } if (Statements.Count == 0 && ColonLocations.Count == 0) { return new ScriptBlock(null, SpanFrom(Start)); } return new ScriptBlock(new StatementCollection(Statements, ColonLocations, new Span(Start.Span.Start, StatementsEnd)), SpanFrom(Start)); } private void ParseExternalSourceStatement(Token start) { Read(); if (CurrentExternalSourceContext != null) { ResyncAt(); ReportSyntaxError(SyntaxErrorType.NestedExternalSourceStatement, SpanFrom(start)); return; } VerifyExpectedToken(TokenType.LeftParenthesis); if (Peek().Type != TokenType.StringLiteral) { ReportSyntaxError(SyntaxErrorType.ExpectedStringLiteral, Peek()); ResyncAt(); return; } string File = ((StringLiteralToken)Read()).Literal; VerifyExpectedToken(TokenType.Comma); if (Peek().Type != TokenType.IntegerLiteral) { ReportSyntaxError(SyntaxErrorType.ExpectedIntegerLiteral, Peek()); ResyncAt(); return; } long Line = ((IntegerLiteralToken)Read()).Literal; VerifyExpectedToken(TokenType.RightParenthesis); CurrentExternalSourceContext = new ExternalSourceContext(); ExternalSourceContext currentExternalSourceContext = CurrentExternalSourceContext; currentExternalSourceContext.File = File; currentExternalSourceContext.Line = Line; currentExternalSourceContext.Start = Peek().Span.Start; currentExternalSourceContext = null; } private void ParseExternalChecksumStatement() { Read(); VerifyExpectedToken(TokenType.LeftParenthesis); if (Peek().Type != TokenType.StringLiteral) { ReportSyntaxError(SyntaxErrorType.ExpectedStringLiteral, Peek()); ResyncAt(); return; } string Filename = ((StringLiteralToken)Read()).Literal; VerifyExpectedToken(TokenType.Comma); if (Peek().Type != TokenType.StringLiteral) { ReportSyntaxError(SyntaxErrorType.ExpectedStringLiteral, Peek()); ResyncAt(); return; } string Guid = ((StringLiteralToken)Read()).Literal; VerifyExpectedToken(TokenType.Comma); if (Peek().Type != TokenType.StringLiteral) { ReportSyntaxError(SyntaxErrorType.ExpectedStringLiteral, Peek()); ResyncAt(); return; } string Checksum = ((StringLiteralToken)Read()).Literal; VerifyExpectedToken(TokenType.RightParenthesis); if (ExternalChecksums != null) { ExternalChecksums.Add(new ExternalChecksum(Filename, Guid, Checksum)); } } private void ParseRegionStatement(Token start, bool statementLevel) { if (statementLevel) { ResyncAt(); ReportSyntaxError(SyntaxErrorType.RegionInsideMethod, SpanFrom(start)); return; } Read(); if (Peek().Type != TokenType.StringLiteral) { ReportSyntaxError(SyntaxErrorType.ExpectedStringLiteral, Peek()); ResyncAt(); return; } string Description = ((StringLiteralToken)Read()).Literal; RegionContext RegionContext = new RegionContext(); RegionContext.Description = Description; RegionContext.Start = Peek().Span.Start; RegionContextStack.Push(RegionContext); } private void ParseEndPreprocessingStatement(Token start, bool statementLevel) { Read(); if (Peek().AsUnreservedKeyword() == TokenType.ExternalSource) { Read(); if (CurrentExternalSourceContext == null) { ReportSyntaxError(SyntaxErrorType.EndExternalSourceWithoutExternalSource, SpanFrom(start)); ResyncAt(); return; } if (ExternalLineMappings != null) { ExternalSourceContext currentExternalSourceContext = CurrentExternalSourceContext; ExternalLineMappings.Add(new ExternalLineMapping(currentExternalSourceContext.Start, start.Span.Start, currentExternalSourceContext.File, currentExternalSourceContext.Line)); currentExternalSourceContext = null; } CurrentExternalSourceContext = null; } else if (Peek().AsUnreservedKeyword() == TokenType.Region) { Read(); if (statementLevel) { ResyncAt(); ReportSyntaxError(SyntaxErrorType.RegionInsideMethod, SpanFrom(start)); return; } if (RegionContextStack.Count == 0) { ReportSyntaxError(SyntaxErrorType.EndRegionWithoutRegion, SpanFrom(start)); ResyncAt(); return; } RegionContext RegionContext = RegionContextStack.Pop(); if (SourceRegions != null) { SourceRegions.Add(new SourceRegion(RegionContext.Start, start.Span.Start, RegionContext.Description)); } } else if (Peek().Type == TokenType.If) { Read(); if (ConditionalCompilationContextStack.Count == 0) { ReportSyntaxError(SyntaxErrorType.CCEndIfWithoutCCIf, SpanFrom(start)); } else { ConditionalCompilationContextStack.Pop(); } } else { ResyncAt(); ReportSyntaxError(SyntaxErrorType.ExpectedEndKind, Peek()); } } private static TypeCode TypeCodeOfCastExpression(IntrinsicType castType) { switch (castType) { case IntrinsicType.Boolean: return TypeCode.Boolean; case IntrinsicType.Byte: return TypeCode.Byte; case IntrinsicType.Char: return TypeCode.Char; case IntrinsicType.Date: return TypeCode.DateTime; case IntrinsicType.Decimal: return TypeCode.Decimal; case IntrinsicType.Double: return TypeCode.Double; case IntrinsicType.Integer: return TypeCode.Int32; case IntrinsicType.Long: return TypeCode.Int64; case IntrinsicType.Object: return TypeCode.Object; case IntrinsicType.Short: return TypeCode.Int16; case IntrinsicType.Single: return TypeCode.Single; case IntrinsicType.String: return TypeCode.String; default: Debug.Assert(condition: false, "Unexpected!"); return TypeCode.Empty; } } private static bool EitherIsTypeCode(TypeCode x, TypeCode y, TypeCode type) { return x == type || y == type; } private static bool IsEitherTypeCode(TypeCode x, TypeCode type1, TypeCode type2) { return x == type1 || x == type2; } private void StartParsing(Scanner scanner, IList errorTable, bool preprocess = false, IDictionary conditionalCompilationConstants = null, IList sourceRegions = null, IList externalLineMappings = null, IList externalChecksums = null) { Scanner = scanner; ErrorTable = errorTable; Preprocess = preprocess; if (conditionalCompilationConstants == null) { ConditionalCompilationConstants = new Dictionary(); } else { ConditionalCompilationConstants = new Dictionary(conditionalCompilationConstants); } ExternalLineMappings = externalLineMappings; SourceRegions = sourceRegions; ExternalChecksums = externalChecksums; ErrorInConstruct = false; AtBeginningOfLine = true; BlockContextStack.Clear(); } private void FinishParsing() { if (CurrentExternalSourceContext != null) { ReportSyntaxError(SyntaxErrorType.ExpectedEndExternalSource, Peek()); } if (RegionContextStack.Count != 0) { ReportSyntaxError(SyntaxErrorType.ExpectedEndRegion, Peek()); } if (ConditionalCompilationContextStack.Count != 0) { ReportSyntaxError(SyntaxErrorType.ExpectedCCEndIf, Peek()); } StartParsing(null, null); } /// /// Parse an entire file. /// /// The scanner to use to fetch the tokens. /// The list of errors produced during parsing. /// A file-level parse tree. public File ParseFile(Scanner scanner, IList errorTable) { StartParsing(scanner, errorTable, preprocess: true); File File = ParseFile(); FinishParsing(); return File; } /// /// Parse an entire file. /// /// The scanner to use to fetch the tokens. /// The list of errors produced during parsing. /// Pre-defined conditional compilation constants. /// Source regions defined in the file. /// External line mappings defined in the file. /// A file-level parse tree. public File ParseFile(Scanner scanner, IList errorTable, IDictionary conditionalCompilationConstants, IList sourceRegions, IList externalLineMappings, IList externalChecksums) { StartParsing(scanner, errorTable, preprocess: true, conditionalCompilationConstants, sourceRegions, externalLineMappings, externalChecksums); File File = ParseFile(); FinishParsing(); return File; } public ScriptBlock ParseScriptFile(Scanner scanner, IList errorTable) { StartParsing(scanner, errorTable, preprocess: true); ScriptBlock File = ParseScriptFile(); FinishParsing(); return File; } public ScriptBlock ParseScriptFile(Scanner scanner, IList errorTable, IDictionary conditionalCompilationConstants, IList sourceRegions, IList externalLineMappings, IList externalChecksums) { StartParsing(scanner, errorTable, preprocess: true, conditionalCompilationConstants, sourceRegions, externalLineMappings, externalChecksums); ScriptBlock File = ParseScriptFile(); FinishParsing(); return File; } /// /// Parse a declaration. /// /// The scanner to use to fetch the tokens. /// The list of errors produced during parsing. /// A declaration-level parse tree. public Declaration ParseDeclaration(Scanner scanner, IList errorTable) { StartParsing(scanner, errorTable); Token terminator = null; Declaration Declaration = ParseDeclaration(ref terminator); FinishParsing(); return Declaration; } /// /// Parse a statement. /// /// The scanner to use to fetch the tokens. /// The list of errors produced during parsing. /// A statement-level parse tree. public Statement ParseStatement(Scanner scanner, IList errorTable) { StartParsing(scanner, errorTable); Token terminator = null; Statement Statement = ParseStatement(ref terminator); FinishParsing(); return Statement; } /// /// Parse an expression. /// /// The scanner to use to fetch the tokens. /// The list of errors produced during parsing. /// An expression-level parse tree. public Expression ParseExpression(Scanner scanner, IList errorTable) { StartParsing(scanner, errorTable); Expression Expression = ParseExpression(); FinishParsing(); return Expression; } /// /// Parse a type name. /// /// The scanner to use to fetch the tokens. /// The list of errors produced during parsing. /// A typename-level parse tree. public TypeName ParseTypeName(Scanner scanner, IList errorTable) { StartParsing(scanner, errorTable); TypeName TypeName = ParseTypeName(allowArrayType: true); FinishParsing(); return TypeName; } }