aspclassic-core/AspClassic.Parser/Parser.cs
Jelle Luteijn 484dbfc9d9 progress
2022-05-15 11:19:49 +02:00

5769 lines
179 KiB
C#

#define DEBUG
using System;
using System.Collections.Generic;
using System.Diagnostics;
using Microsoft.VisualBasic.CompilerServices;
namespace AspClassic.Parser;
/// <summary>
/// A parser for the Visual Basic .NET language based on the grammar
/// documented in the Language Specification.
/// </summary>
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<SyntaxError> ErrorTable;
private IList<ExternalLineMapping> ExternalLineMappings;
private IList<SourceRegion> SourceRegions;
private IList<ExternalChecksum> ExternalChecksums;
private IDictionary<string, object> ConditionalCompilationConstants;
private bool ErrorInConstruct;
private bool AtBeginningOfLine;
private bool Preprocess;
private bool CanContinueWithoutLineTerminator;
private Stack<TreeType> BlockContextStack;
private ExternalSourceContext CurrentExternalSourceContext;
private Stack<RegionContext> RegionContextStack;
private Stack<ConditionalCompilationContext> ConditionalCompilationContextStack;
private bool Disposed;
public Parser()
{
BlockContextStack = new Stack<TreeType>();
RegionContextStack = new Stack<RegionContext>();
ConditionalCompilationContextStack = new Stack<ConditionalCompilationContext>();
Disposed = false;
}
/// <summary>
/// Disposes the parser.
/// </summary>
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<Comment> ParseTrailingComments()
{
List<Comment> Comments = new List<Comment>();
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<Declaration> 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<TypeName> TypeArguments = new List<TypeName>();
List<Location> CommaLocations = new List<Location>();
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<Location> CommaLocations = new List<Location>();
Debug.Assert(Peek().Type == TokenType.LeftParenthesis);
if (startType == null)
{
startType = Peek();
}
Read();
List<Argument> 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<Argument>();
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<Initializer> Initializers = new List<Initializer>();
List<Location> CommaLocations = new List<Location>();
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<Argument> Arguments = new List<Argument>();
List<Location> CommaLocations = new List<Location>();
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<Expression> Expressions = new List<Expression>();
List<Location> CommaLocations = new List<Location>();
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<Comment> 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<Comment> 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<Comment> 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<Comment> 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<Comment> 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<Statement> CatchBlocks = new List<Statement>();
StatementCollection CatchBlockList = null;
FinallyBlockStatement FinallyBlock = null;
List<Comment> 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<Comment> 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<Comment> 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<Location> CommaLocations = new List<Location>();
List<CaseClause> Cases = new List<CaseClause>();
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<Statement> CaseBlocks = new List<Statement>();
StatementCollection CaseBlockList = null;
CaseElseBlockStatement CaseElseBlockStatement = null;
List<Comment> 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<Comment> 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<Comment> 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<Statement> ElseIfBlocks = new List<Statement>();
StatementCollection ElseIfBlockList = null;
ElseBlockStatement ElseBlockStatement = null;
List<Comment> 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<Comment> 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<Comment> 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<Comment> Comments = new List<Comment>();
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<Comment>(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<Comment> Comments = new List<Comment>();
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<Comment>(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<Comment> Comments, ref Statement endStatement)
{
List<Statement> Statements = new List<Statement>();
List<Location> ColonLocations = new List<Location>();
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<Statement> Statements = new List<Statement>();
List<Location> ColonLocations = new List<Location>();
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<Modifier> Modifiers = new List<Modifier>();
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<Modifier> Modifiers = new List<Modifier>();
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<Location> VariableNamesCommaLocations = new List<Location>();
List<VariableName> VariableNames = new List<VariableName>();
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<VariableDeclarator> VariableDeclarators = new List<VariableDeclarator>();
List<Location> DeclarationsCommaLocations = new List<Location>();
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<VariableName> VariableNames = new List<VariableName>();
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<Attribute> Attributes = new List<Attribute>();
List<Location> CommaLocations = new List<Location>();
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<AttributeCollection> AttributeBlocks = new List<AttributeCollection>();
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<Location> CommaLocations = new List<Location>();
List<Name> Names = new List<Name>();
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<Comment> 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<Comment> 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<Comment> 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<Comment> 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<Comment> 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<Comment> 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<Comment> 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<Comment> 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<Location> CommaLocations = new List<Location>();
List<TypeName> Types = new List<TypeName>();
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<Comment> 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<Import> ImportMembers = new List<Import>();
List<Location> CommaLocations = new List<Location>();
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<Comment> Comments = new List<Comment>();
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<Comment> Comments = new List<Comment>();
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<Comment> Comments, ref EndBlockDeclaration endDeclaration)
{
List<Declaration> Declarations = new List<Declaration>();
List<Location> ColonLocations = new List<Location>();
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<Parameter> Parameters = new List<Parameter>();
List<Location> CommaLocations = new List<Location>();
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<Location> CommaLocations = new List<Location>();
List<TypeName> Types = new List<TypeName>();
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<TypeParameter> TypeParameters = new List<TypeParameter>();
List<Location> CommaLocations = new List<Location>();
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<Declaration> Declarations = new List<Declaration>();
List<Location> ColonLocations = new List<Location>();
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<Statement> Statements = new List<Statement>();
List<Location> ColonLocations = new List<Location>();
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<SyntaxError> errorTable, bool preprocess = false, IDictionary<string, object> conditionalCompilationConstants = null, IList<SourceRegion> sourceRegions = null, IList<ExternalLineMapping> externalLineMappings = null, IList<ExternalChecksum> externalChecksums = null)
{
Scanner = scanner;
ErrorTable = errorTable;
Preprocess = preprocess;
if (conditionalCompilationConstants == null)
{
ConditionalCompilationConstants = new Dictionary<string, object>();
}
else
{
ConditionalCompilationConstants = new Dictionary<string, object>(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);
}
/// <summary>
/// Parse an entire file.
/// </summary>
/// <param name="scanner">The scanner to use to fetch the tokens.</param>
/// <param name="errorTable">The list of errors produced during parsing.</param>
/// <returns>A file-level parse tree.</returns>
public File ParseFile(Scanner scanner, IList<SyntaxError> errorTable)
{
StartParsing(scanner, errorTable, preprocess: true);
File File = ParseFile();
FinishParsing();
return File;
}
/// <summary>
/// Parse an entire file.
/// </summary>
/// <param name="scanner">The scanner to use to fetch the tokens.</param>
/// <param name="errorTable">The list of errors produced during parsing.</param>
/// <param name="conditionalCompilationConstants">Pre-defined conditional compilation constants.</param>
/// <param name="sourceRegions">Source regions defined in the file.</param>
/// <param name="externalLineMappings">External line mappings defined in the file.</param>
/// <returns>A file-level parse tree.</returns>
public File ParseFile(Scanner scanner, IList<SyntaxError> errorTable, IDictionary<string, object> conditionalCompilationConstants, IList<SourceRegion> sourceRegions, IList<ExternalLineMapping> externalLineMappings, IList<ExternalChecksum> externalChecksums)
{
StartParsing(scanner, errorTable, preprocess: true, conditionalCompilationConstants, sourceRegions, externalLineMappings, externalChecksums);
File File = ParseFile();
FinishParsing();
return File;
}
public ScriptBlock ParseScriptFile(Scanner scanner, IList<SyntaxError> errorTable)
{
StartParsing(scanner, errorTable, preprocess: true);
ScriptBlock File = ParseScriptFile();
FinishParsing();
return File;
}
public ScriptBlock ParseScriptFile(Scanner scanner, IList<SyntaxError> errorTable, IDictionary<string, object> conditionalCompilationConstants, IList<SourceRegion> sourceRegions, IList<ExternalLineMapping> externalLineMappings, IList<ExternalChecksum> externalChecksums)
{
StartParsing(scanner, errorTable, preprocess: true, conditionalCompilationConstants, sourceRegions, externalLineMappings, externalChecksums);
ScriptBlock File = ParseScriptFile();
FinishParsing();
return File;
}
/// <summary>
/// Parse a declaration.
/// </summary>
/// <param name="scanner">The scanner to use to fetch the tokens.</param>
/// <param name="errorTable">The list of errors produced during parsing.</param>
/// <returns>A declaration-level parse tree.</returns>
public Declaration ParseDeclaration(Scanner scanner, IList<SyntaxError> errorTable)
{
StartParsing(scanner, errorTable);
Token terminator = null;
Declaration Declaration = ParseDeclaration(ref terminator);
FinishParsing();
return Declaration;
}
/// <summary>
/// Parse a statement.
/// </summary>
/// <param name="scanner">The scanner to use to fetch the tokens.</param>
/// <param name="errorTable">The list of errors produced during parsing.</param>
/// <returns>A statement-level parse tree.</returns>
public Statement ParseStatement(Scanner scanner, IList<SyntaxError> errorTable)
{
StartParsing(scanner, errorTable);
Token terminator = null;
Statement Statement = ParseStatement(ref terminator);
FinishParsing();
return Statement;
}
/// <summary>
/// Parse an expression.
/// </summary>
/// <param name="scanner">The scanner to use to fetch the tokens.</param>
/// <param name="errorTable">The list of errors produced during parsing.</param>
/// <returns>An expression-level parse tree.</returns>
public Expression ParseExpression(Scanner scanner, IList<SyntaxError> errorTable)
{
StartParsing(scanner, errorTable);
Expression Expression = ParseExpression();
FinishParsing();
return Expression;
}
/// <summary>
/// Parse a type name.
/// </summary>
/// <param name="scanner">The scanner to use to fetch the tokens.</param>
/// <param name="errorTable">The list of errors produced during parsing.</param>
/// <returns>A typename-level parse tree.</returns>
public TypeName ParseTypeName(Scanner scanner, IList<SyntaxError> errorTable)
{
StartParsing(scanner, errorTable);
TypeName TypeName = ParseTypeName(allowArrayType: true);
FinishParsing();
return TypeName;
}
}