729 lines
32 KiB
C#
729 lines
32 KiB
C#
using System;
|
|||
|
|
using System.Globalization;
|
||
|
|
using System.IO;
|
||
|
|
using Microsoft.CodeAnalysis.Syntax.InternalSyntax;
|
||
|
|
|
||
|
|
namespace Microsoft.CodeAnalysis.CSharp.Syntax.InternalSyntax;
|
||
|
|
|
||
|
|
internal class DirectiveParser : SyntaxParser
|
||
|
|
{
|
||
|
|
private const int MAX_DIRECTIVE_IDENTIFIER_WIDTH = 128;
|
||
|
|
|
||
|
|
private readonly DirectiveStack _context;
|
||
|
|
|
||
|
|
private const int MaxLineValue = 16707565;
|
||
|
|
|
||
|
|
private const int MaxCharacterValue = 65536;
|
||
|
|
|
||
|
|
internal DirectiveParser(Lexer lexer, DirectiveStack context)
|
||
|
|
: base(lexer, LexerMode.Directive, null, null, allowModeReset: false)
|
||
|
|
{
|
||
|
|
_context = context;
|
||
|
|
}
|
||
|
|
|
||
|
|
public CSharpSyntaxNode ParseDirective(bool isActive, bool endIsActive, bool isAfterFirstTokenInFile, bool isAfterNonWhitespaceOnLine)
|
||
|
|
{
|
||
|
|
//IL_021e: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_0224: Invalid comparison between Unknown and I4
|
||
|
|
int position = lexer.TextWindow.Position;
|
||
|
|
SyntaxToken syntaxToken = EatToken(SyntaxKind.HashToken, reportError: false);
|
||
|
|
if (isAfterNonWhitespaceOnLine)
|
||
|
|
{
|
||
|
|
syntaxToken = AddError(syntaxToken, ErrorCode.ERR_BadDirectivePlacement);
|
||
|
|
}
|
||
|
|
SyntaxKind contextualKind = base.CurrentToken.ContextualKind;
|
||
|
|
switch (contextualKind)
|
||
|
|
{
|
||
|
|
case SyntaxKind.IfKeyword:
|
||
|
|
return ParseIfDirective(syntaxToken, EatContextualToken(contextualKind), isActive);
|
||
|
|
case SyntaxKind.ElifKeyword:
|
||
|
|
return ParseElifDirective(syntaxToken, EatContextualToken(contextualKind), isActive, endIsActive);
|
||
|
|
case SyntaxKind.ElseKeyword:
|
||
|
|
return ParseElseDirective(syntaxToken, EatContextualToken(contextualKind), isActive, endIsActive);
|
||
|
|
case SyntaxKind.EndIfKeyword:
|
||
|
|
return ParseEndIfDirective(syntaxToken, EatContextualToken(contextualKind), isActive, endIsActive);
|
||
|
|
case SyntaxKind.RegionKeyword:
|
||
|
|
return ParseRegionDirective(syntaxToken, EatContextualToken(contextualKind), isActive);
|
||
|
|
case SyntaxKind.EndRegionKeyword:
|
||
|
|
return ParseEndRegionDirective(syntaxToken, EatContextualToken(contextualKind), isActive);
|
||
|
|
case SyntaxKind.DefineKeyword:
|
||
|
|
case SyntaxKind.UndefKeyword:
|
||
|
|
return ParseDefineOrUndefDirective(syntaxToken, EatContextualToken(contextualKind), isActive, isAfterFirstTokenInFile && !isAfterNonWhitespaceOnLine);
|
||
|
|
case SyntaxKind.WarningKeyword:
|
||
|
|
case SyntaxKind.ErrorKeyword:
|
||
|
|
return ParseErrorOrWarningDirective(syntaxToken, EatContextualToken(contextualKind), isActive);
|
||
|
|
case SyntaxKind.LineKeyword:
|
||
|
|
{
|
||
|
|
SyntaxToken syntaxToken3 = EatContextualToken(contextualKind);
|
||
|
|
return (base.CurrentToken.Kind == SyntaxKind.OpenParenToken) ? ParseLineSpanDirective(syntaxToken, syntaxToken3, isActive) : ParseLineDirective(syntaxToken, syntaxToken3, isActive);
|
||
|
|
}
|
||
|
|
case SyntaxKind.PragmaKeyword:
|
||
|
|
return ParsePragmaDirective(syntaxToken, EatContextualToken(contextualKind), isActive);
|
||
|
|
case SyntaxKind.ReferenceKeyword:
|
||
|
|
return ParseReferenceDirective(syntaxToken, EatContextualToken(contextualKind), isActive, isAfterFirstTokenInFile && !isAfterNonWhitespaceOnLine);
|
||
|
|
case SyntaxKind.LoadKeyword:
|
||
|
|
return ParseLoadDirective(syntaxToken, EatContextualToken(contextualKind), isActive, isAfterFirstTokenInFile && !isAfterNonWhitespaceOnLine);
|
||
|
|
case SyntaxKind.NullableKeyword:
|
||
|
|
return ParseNullableDirective(syntaxToken, EatContextualToken(contextualKind), isActive);
|
||
|
|
default:
|
||
|
|
{
|
||
|
|
if ((int)((ParseOptions)lexer.Options).Kind == 1 && contextualKind == SyntaxKind.ExclamationToken && position == 0 && !((GreenNode)syntaxToken).HasTrailingTrivia)
|
||
|
|
{
|
||
|
|
return ParseShebangDirective(syntaxToken, EatToken(SyntaxKind.ExclamationToken), isActive);
|
||
|
|
}
|
||
|
|
SyntaxToken syntaxToken2 = EatToken(SyntaxKind.IdentifierToken, reportError: false);
|
||
|
|
SyntaxToken endOfDirectiveToken = ParseEndOfDirective(ignoreErrors: true);
|
||
|
|
if (!isAfterNonWhitespaceOnLine)
|
||
|
|
{
|
||
|
|
if (!((GreenNode)syntaxToken2).IsMissing)
|
||
|
|
{
|
||
|
|
syntaxToken2 = AddError(syntaxToken2, ErrorCode.ERR_PPDirectiveExpected);
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
syntaxToken = AddError(syntaxToken, ErrorCode.ERR_PPDirectiveExpected);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return SyntaxFactory.BadDirectiveTrivia(syntaxToken, syntaxToken2, endOfDirectiveToken, isActive);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private DirectiveTriviaSyntax ParseIfDirective(SyntaxToken hash, SyntaxToken keyword, bool isActive)
|
||
|
|
{
|
||
|
|
ExpressionSyntax expressionSyntax = ParseExpression();
|
||
|
|
SyntaxToken endOfDirectiveToken = ParseEndOfDirective(ignoreErrors: false);
|
||
|
|
bool flag = EvaluateBool(expressionSyntax);
|
||
|
|
bool branchTaken = isActive && flag;
|
||
|
|
return SyntaxFactory.IfDirectiveTrivia(hash, keyword, expressionSyntax, endOfDirectiveToken, isActive, branchTaken, flag);
|
||
|
|
}
|
||
|
|
|
||
|
|
private DirectiveTriviaSyntax ParseElifDirective(SyntaxToken hash, SyntaxToken keyword, bool isActive, bool endIsActive)
|
||
|
|
{
|
||
|
|
ExpressionSyntax expressionSyntax = ParseExpression();
|
||
|
|
SyntaxToken syntaxToken = ParseEndOfDirective(ignoreErrors: false);
|
||
|
|
if (_context.HasPreviousIfOrElif())
|
||
|
|
{
|
||
|
|
bool flag = EvaluateBool(expressionSyntax);
|
||
|
|
bool branchTaken = endIsActive && flag && !_context.PreviousBranchTaken();
|
||
|
|
return SyntaxFactory.ElifDirectiveTrivia(hash, keyword, expressionSyntax, syntaxToken, endIsActive, branchTaken, flag);
|
||
|
|
}
|
||
|
|
syntaxToken = syntaxToken.TokenWithLeadingTrivia(SyntaxList.Concat((GreenNode)(object)SyntaxFactory.DisabledText(((GreenNode)expressionSyntax).ToFullString()), syntaxToken.GetLeadingTrivia()));
|
||
|
|
if (_context.HasUnfinishedRegion())
|
||
|
|
{
|
||
|
|
return AddError(SyntaxFactory.BadDirectiveTrivia(hash, keyword, syntaxToken, isActive), ErrorCode.ERR_EndRegionDirectiveExpected);
|
||
|
|
}
|
||
|
|
if (_context.HasUnfinishedIf())
|
||
|
|
{
|
||
|
|
return AddError(SyntaxFactory.BadDirectiveTrivia(hash, keyword, syntaxToken, isActive), ErrorCode.ERR_EndifDirectiveExpected);
|
||
|
|
}
|
||
|
|
return AddError(SyntaxFactory.BadDirectiveTrivia(hash, keyword, syntaxToken, isActive), ErrorCode.ERR_UnexpectedDirective);
|
||
|
|
}
|
||
|
|
|
||
|
|
private DirectiveTriviaSyntax ParseElseDirective(SyntaxToken hash, SyntaxToken keyword, bool isActive, bool endIsActive)
|
||
|
|
{
|
||
|
|
SyntaxToken endOfDirectiveToken = ParseEndOfDirective(ignoreErrors: false);
|
||
|
|
if (_context.HasPreviousIfOrElif())
|
||
|
|
{
|
||
|
|
bool branchTaken = endIsActive && !_context.PreviousBranchTaken();
|
||
|
|
return SyntaxFactory.ElseDirectiveTrivia(hash, keyword, endOfDirectiveToken, endIsActive, branchTaken);
|
||
|
|
}
|
||
|
|
if (_context.HasUnfinishedRegion())
|
||
|
|
{
|
||
|
|
return AddError(SyntaxFactory.BadDirectiveTrivia(hash, keyword, endOfDirectiveToken, isActive), ErrorCode.ERR_EndRegionDirectiveExpected);
|
||
|
|
}
|
||
|
|
if (_context.HasUnfinishedIf())
|
||
|
|
{
|
||
|
|
return AddError(SyntaxFactory.BadDirectiveTrivia(hash, keyword, endOfDirectiveToken, isActive), ErrorCode.ERR_EndifDirectiveExpected);
|
||
|
|
}
|
||
|
|
return AddError(SyntaxFactory.BadDirectiveTrivia(hash, keyword, endOfDirectiveToken, isActive), ErrorCode.ERR_UnexpectedDirective);
|
||
|
|
}
|
||
|
|
|
||
|
|
private DirectiveTriviaSyntax ParseEndIfDirective(SyntaxToken hash, SyntaxToken keyword, bool isActive, bool endIsActive)
|
||
|
|
{
|
||
|
|
SyntaxToken endOfDirectiveToken = ParseEndOfDirective(ignoreErrors: false);
|
||
|
|
if (_context.HasUnfinishedIf())
|
||
|
|
{
|
||
|
|
return SyntaxFactory.EndIfDirectiveTrivia(hash, keyword, endOfDirectiveToken, endIsActive);
|
||
|
|
}
|
||
|
|
if (_context.HasUnfinishedRegion())
|
||
|
|
{
|
||
|
|
return AddError(SyntaxFactory.BadDirectiveTrivia(hash, keyword, endOfDirectiveToken, isActive), ErrorCode.ERR_EndRegionDirectiveExpected);
|
||
|
|
}
|
||
|
|
return AddError(SyntaxFactory.BadDirectiveTrivia(hash, keyword, endOfDirectiveToken, isActive), ErrorCode.ERR_UnexpectedDirective);
|
||
|
|
}
|
||
|
|
|
||
|
|
private DirectiveTriviaSyntax ParseRegionDirective(SyntaxToken hash, SyntaxToken keyword, bool isActive)
|
||
|
|
{
|
||
|
|
return SyntaxFactory.RegionDirectiveTrivia(hash, keyword, ParseEndOfDirectiveWithOptionalPreprocessingMessage(), isActive);
|
||
|
|
}
|
||
|
|
|
||
|
|
private DirectiveTriviaSyntax ParseEndRegionDirective(SyntaxToken hash, SyntaxToken keyword, bool isActive)
|
||
|
|
{
|
||
|
|
SyntaxToken endOfDirectiveToken = ParseEndOfDirectiveWithOptionalPreprocessingMessage();
|
||
|
|
if (_context.HasUnfinishedRegion())
|
||
|
|
{
|
||
|
|
return SyntaxFactory.EndRegionDirectiveTrivia(hash, keyword, endOfDirectiveToken, isActive);
|
||
|
|
}
|
||
|
|
if (_context.HasUnfinishedIf())
|
||
|
|
{
|
||
|
|
return AddError(SyntaxFactory.BadDirectiveTrivia(hash, keyword, endOfDirectiveToken, isActive), ErrorCode.ERR_EndifDirectiveExpected);
|
||
|
|
}
|
||
|
|
return AddError(SyntaxFactory.BadDirectiveTrivia(hash, keyword, endOfDirectiveToken, isActive), ErrorCode.ERR_UnexpectedDirective);
|
||
|
|
}
|
||
|
|
|
||
|
|
private DirectiveTriviaSyntax ParseDefineOrUndefDirective(SyntaxToken hash, SyntaxToken keyword, bool isActive, bool isFollowingToken)
|
||
|
|
{
|
||
|
|
if (isFollowingToken)
|
||
|
|
{
|
||
|
|
keyword = AddError(keyword, ErrorCode.ERR_PPDefFollowsToken);
|
||
|
|
}
|
||
|
|
SyntaxToken identifier = EatToken(SyntaxKind.IdentifierToken, ErrorCode.ERR_IdentifierExpected);
|
||
|
|
identifier = TruncateIdentifier(identifier);
|
||
|
|
SyntaxToken endOfDirectiveToken = ParseEndOfDirective(((GreenNode)identifier).IsMissing);
|
||
|
|
if (keyword.Kind == SyntaxKind.DefineKeyword)
|
||
|
|
{
|
||
|
|
return SyntaxFactory.DefineDirectiveTrivia(hash, keyword, identifier, endOfDirectiveToken, isActive);
|
||
|
|
}
|
||
|
|
return SyntaxFactory.UndefDirectiveTrivia(hash, keyword, identifier, endOfDirectiveToken, isActive);
|
||
|
|
}
|
||
|
|
|
||
|
|
private DirectiveTriviaSyntax ParseErrorOrWarningDirective(SyntaxToken hash, SyntaxToken keyword, bool isActive)
|
||
|
|
{
|
||
|
|
//IL_002c: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_0031: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_0035: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_003a: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_007a: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_007f: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_0083: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_0088: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
SyntaxToken syntaxToken = ParseEndOfDirectiveWithOptionalPreprocessingMessage();
|
||
|
|
bool flag = keyword.Kind == SyntaxKind.ErrorKeyword;
|
||
|
|
if (isActive)
|
||
|
|
{
|
||
|
|
StringWriter stringWriter = new StringWriter(CultureInfo.InvariantCulture);
|
||
|
|
int num = 0;
|
||
|
|
bool flag2 = true;
|
||
|
|
Enumerator<CSharpSyntaxNode> enumerator = keyword.TrailingTrivia.GetEnumerator();
|
||
|
|
while (enumerator.MoveNext())
|
||
|
|
{
|
||
|
|
CSharpSyntaxNode current = enumerator.Current;
|
||
|
|
if (flag2)
|
||
|
|
{
|
||
|
|
if (current.Kind == SyntaxKind.WhitespaceTrivia)
|
||
|
|
{
|
||
|
|
continue;
|
||
|
|
}
|
||
|
|
flag2 = false;
|
||
|
|
}
|
||
|
|
((GreenNode)current).WriteTo((TextWriter)stringWriter, true, true);
|
||
|
|
num += ((GreenNode)current).FullWidth;
|
||
|
|
}
|
||
|
|
enumerator = syntaxToken.LeadingTrivia.GetEnumerator();
|
||
|
|
while (enumerator.MoveNext())
|
||
|
|
{
|
||
|
|
CSharpSyntaxNode current2 = enumerator.Current;
|
||
|
|
((GreenNode)current2).WriteTo((TextWriter)stringWriter, true, true);
|
||
|
|
num += ((GreenNode)current2).FullWidth;
|
||
|
|
}
|
||
|
|
int offset = ((GreenNode)syntaxToken).GetLeadingTriviaWidth() - num;
|
||
|
|
string text = stringWriter.ToString();
|
||
|
|
syntaxToken = AddError(syntaxToken, offset, num, flag ? ErrorCode.ERR_ErrorDirective : ErrorCode.WRN_WarningDirective, text);
|
||
|
|
if (flag)
|
||
|
|
{
|
||
|
|
LanguageVersion result;
|
||
|
|
if (text.Equals("version", StringComparison.Ordinal))
|
||
|
|
{
|
||
|
|
string productVersion = CommonCompiler.GetProductVersion(typeof(CSharpCompiler));
|
||
|
|
LanguageVersion specifiedLanguageVersion = base.Options.SpecifiedLanguageVersion;
|
||
|
|
LanguageVersion languageVersion = specifiedLanguageVersion.MapSpecifiedToEffectiveVersion();
|
||
|
|
string text2 = ((specifiedLanguageVersion == languageVersion) ? specifiedLanguageVersion.ToDisplayString() : (specifiedLanguageVersion.ToDisplayString() + " (" + languageVersion.ToDisplayString() + ")"));
|
||
|
|
syntaxToken = AddError(syntaxToken, offset, num, ErrorCode.ERR_CompilerAndLanguageVersion, productVersion, text2);
|
||
|
|
}
|
||
|
|
else if (base.Options.LanguageVersion != LanguageVersion.Preview && text.StartsWith("version:", StringComparison.Ordinal) && LanguageVersionFacts.TryParse(text.Substring("version:".Length), out result))
|
||
|
|
{
|
||
|
|
ErrorCode errorCode = base.Options.LanguageVersion.GetErrorCode();
|
||
|
|
syntaxToken = AddError(syntaxToken, offset, num, errorCode, "version", new CSharpRequiredLanguageVersion(result));
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
if (flag)
|
||
|
|
{
|
||
|
|
return SyntaxFactory.ErrorDirectiveTrivia(hash, keyword, syntaxToken, isActive);
|
||
|
|
}
|
||
|
|
return SyntaxFactory.WarningDirectiveTrivia(hash, keyword, syntaxToken, isActive);
|
||
|
|
}
|
||
|
|
|
||
|
|
private DirectiveTriviaSyntax ParseLineDirective(SyntaxToken hash, SyntaxToken id, bool isActive)
|
||
|
|
{
|
||
|
|
SyntaxToken file = null;
|
||
|
|
bool afterLineNumber = false;
|
||
|
|
SyntaxKind kind = base.CurrentToken.Kind;
|
||
|
|
SyntaxToken syntaxToken;
|
||
|
|
if (kind == SyntaxKind.DefaultKeyword || kind == SyntaxKind.HiddenKeyword)
|
||
|
|
{
|
||
|
|
syntaxToken = EatToken();
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
syntaxToken = EatToken(SyntaxKind.NumericLiteralToken, ErrorCode.ERR_InvalidLineNumber, isActive);
|
||
|
|
afterLineNumber = true;
|
||
|
|
if (isActive && !((GreenNode)syntaxToken).IsMissing && syntaxToken.Kind == SyntaxKind.NumericLiteralToken)
|
||
|
|
{
|
||
|
|
if ((int)syntaxToken.Value < 1)
|
||
|
|
{
|
||
|
|
syntaxToken = AddError(syntaxToken, ErrorCode.ERR_InvalidLineNumber);
|
||
|
|
}
|
||
|
|
else if ((int)syntaxToken.Value > 16707565)
|
||
|
|
{
|
||
|
|
syntaxToken = AddError(syntaxToken, ErrorCode.WRN_TooManyLinesForDebugger);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
if (base.CurrentToken.Kind == SyntaxKind.StringLiteralToken && (((GreenNode)syntaxToken).IsMissing || ((GreenNode)syntaxToken).GetTrailingTriviaWidth() > 0 || ((GreenNode)base.CurrentToken).GetLeadingTriviaWidth() > 0))
|
||
|
|
{
|
||
|
|
file = EatToken();
|
||
|
|
afterLineNumber = false;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
SyntaxToken endOfDirectiveToken = ParseEndOfDirective(((GreenNode)syntaxToken).IsMissing || !isActive, afterPragma: false, afterLineNumber);
|
||
|
|
return SyntaxFactory.LineDirectiveTrivia(hash, id, syntaxToken, file, endOfDirectiveToken, isActive);
|
||
|
|
}
|
||
|
|
|
||
|
|
private LineSpanDirectiveTriviaSyntax ParseLineSpanDirective(SyntaxToken hash, SyntaxToken lineKeyword, bool isActive)
|
||
|
|
{
|
||
|
|
bool reportError = isActive;
|
||
|
|
int line;
|
||
|
|
int character;
|
||
|
|
LineDirectivePositionSyntax lineDirectivePositionSyntax = ParseLineDirectivePosition(ref reportError, out line, out character);
|
||
|
|
if (noTriviaBetween(lineKeyword, lineDirectivePositionSyntax.GetFirstToken()))
|
||
|
|
{
|
||
|
|
lineDirectivePositionSyntax = AddError(lineDirectivePositionSyntax, ErrorCode.ERR_LineSpanDirectiveRequiresSpace);
|
||
|
|
}
|
||
|
|
SyntaxToken syntaxToken = EatToken(SyntaxKind.MinusToken, reportError);
|
||
|
|
if (((GreenNode)syntaxToken).IsMissing)
|
||
|
|
{
|
||
|
|
reportError = false;
|
||
|
|
}
|
||
|
|
int line2;
|
||
|
|
int character2;
|
||
|
|
LineDirectivePositionSyntax lineDirectivePositionSyntax2 = ParseLineDirectivePosition(ref reportError, out line2, out character2);
|
||
|
|
if (reportError && (line2 < line || (line2 == line && character2 < character)))
|
||
|
|
{
|
||
|
|
lineDirectivePositionSyntax2 = AddError(lineDirectivePositionSyntax2, ErrorCode.ERR_LineSpanDirectiveEndLessThanStart);
|
||
|
|
}
|
||
|
|
int value;
|
||
|
|
SyntaxToken syntaxToken2 = ((base.CurrentToken.Kind == SyntaxKind.NumericLiteralToken) ? ParseLineDirectiveNumericLiteral(ref reportError, 1, 65536, out value) : null);
|
||
|
|
if (noTriviaBetween(lineDirectivePositionSyntax2.GetLastToken(), syntaxToken2))
|
||
|
|
{
|
||
|
|
syntaxToken2 = AddError(syntaxToken2, ErrorCode.ERR_LineSpanDirectiveRequiresSpace);
|
||
|
|
}
|
||
|
|
SyntaxToken syntaxToken3 = EatToken(SyntaxKind.StringLiteralToken, ErrorCode.ERR_MissingPPFile, reportError);
|
||
|
|
if (((GreenNode)syntaxToken3).IsMissing)
|
||
|
|
{
|
||
|
|
reportError = false;
|
||
|
|
}
|
||
|
|
if (noTriviaBetween(syntaxToken2 ?? lineDirectivePositionSyntax2.GetLastToken(), syntaxToken3))
|
||
|
|
{
|
||
|
|
syntaxToken3 = AddError(syntaxToken3, ErrorCode.ERR_LineSpanDirectiveRequiresSpace);
|
||
|
|
}
|
||
|
|
SyntaxToken endOfDirectiveToken = ParseEndOfDirective(!reportError);
|
||
|
|
return SyntaxFactory.LineSpanDirectiveTrivia(hash, lineKeyword, lineDirectivePositionSyntax, syntaxToken, lineDirectivePositionSyntax2, syntaxToken2, syntaxToken3, endOfDirectiveToken, isActive);
|
||
|
|
static bool noTriviaBetween(SyntaxToken token1, SyntaxToken token2)
|
||
|
|
{
|
||
|
|
if (token1 != null && !((GreenNode)token1).IsMissing && token2 != null && !((GreenNode)token2).IsMissing)
|
||
|
|
{
|
||
|
|
return LanguageParser.NoTriviaBetween(token1, token2);
|
||
|
|
}
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private LineDirectivePositionSyntax ParseLineDirectivePosition(ref bool reportError, out int line, out int character)
|
||
|
|
{
|
||
|
|
SyntaxToken syntaxToken = EatToken(SyntaxKind.OpenParenToken, reportError);
|
||
|
|
if (((GreenNode)syntaxToken).IsMissing)
|
||
|
|
{
|
||
|
|
reportError = false;
|
||
|
|
}
|
||
|
|
SyntaxToken line2 = ParseLineDirectiveNumericLiteral(ref reportError, 1, 16707565, out line);
|
||
|
|
SyntaxToken syntaxToken2 = EatToken(SyntaxKind.CommaToken, reportError);
|
||
|
|
if (((GreenNode)syntaxToken2).IsMissing)
|
||
|
|
{
|
||
|
|
reportError = false;
|
||
|
|
}
|
||
|
|
SyntaxToken character2 = ParseLineDirectiveNumericLiteral(ref reportError, 1, 65536, out character);
|
||
|
|
SyntaxToken syntaxToken3 = EatToken(SyntaxKind.CloseParenToken, reportError);
|
||
|
|
if (((GreenNode)syntaxToken3).IsMissing)
|
||
|
|
{
|
||
|
|
reportError = false;
|
||
|
|
}
|
||
|
|
return SyntaxFactory.LineDirectivePosition(syntaxToken, line2, syntaxToken2, character2, syntaxToken3);
|
||
|
|
}
|
||
|
|
|
||
|
|
private SyntaxToken ParseLineDirectiveNumericLiteral(ref bool reportError, int minValue, int maxValue, out int value)
|
||
|
|
{
|
||
|
|
SyntaxToken syntaxToken = EatToken(SyntaxKind.NumericLiteralToken, ErrorCode.ERR_LineSpanDirectiveInvalidValue, reportError);
|
||
|
|
value = 0;
|
||
|
|
if (((GreenNode)syntaxToken).IsMissing)
|
||
|
|
{
|
||
|
|
reportError = false;
|
||
|
|
}
|
||
|
|
else if (syntaxToken.Kind == SyntaxKind.NumericLiteralToken)
|
||
|
|
{
|
||
|
|
value = (int)syntaxToken.Value;
|
||
|
|
if (value < minValue || value > maxValue)
|
||
|
|
{
|
||
|
|
syntaxToken = AddError(syntaxToken, ErrorCode.ERR_LineSpanDirectiveInvalidValue);
|
||
|
|
reportError = false;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return syntaxToken;
|
||
|
|
}
|
||
|
|
|
||
|
|
private DirectiveTriviaSyntax ParseReferenceDirective(SyntaxToken hash, SyntaxToken keyword, bool isActive, bool isFollowingToken)
|
||
|
|
{
|
||
|
|
//IL_0009: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
if (isActive)
|
||
|
|
{
|
||
|
|
if ((int)((ParseOptions)base.Options).Kind == 0)
|
||
|
|
{
|
||
|
|
keyword = AddError(keyword, ErrorCode.ERR_ReferenceDirectiveOnlyAllowedInScripts);
|
||
|
|
}
|
||
|
|
else if (isFollowingToken)
|
||
|
|
{
|
||
|
|
keyword = AddError(keyword, ErrorCode.ERR_PPReferenceFollowsToken);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
SyntaxToken syntaxToken = EatToken(SyntaxKind.StringLiteralToken, ErrorCode.ERR_ExpectedPPFile, isActive);
|
||
|
|
SyntaxToken endOfDirectiveToken = ParseEndOfDirective(((GreenNode)syntaxToken).IsMissing || !isActive);
|
||
|
|
return SyntaxFactory.ReferenceDirectiveTrivia(hash, keyword, syntaxToken, endOfDirectiveToken, isActive);
|
||
|
|
}
|
||
|
|
|
||
|
|
private DirectiveTriviaSyntax ParseLoadDirective(SyntaxToken hash, SyntaxToken keyword, bool isActive, bool isFollowingToken)
|
||
|
|
{
|
||
|
|
//IL_0009: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
if (isActive)
|
||
|
|
{
|
||
|
|
if ((int)((ParseOptions)base.Options).Kind == 0)
|
||
|
|
{
|
||
|
|
keyword = AddError(keyword, ErrorCode.ERR_LoadDirectiveOnlyAllowedInScripts);
|
||
|
|
}
|
||
|
|
else if (isFollowingToken)
|
||
|
|
{
|
||
|
|
keyword = AddError(keyword, ErrorCode.ERR_PPLoadFollowsToken);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
SyntaxToken syntaxToken = EatToken(SyntaxKind.StringLiteralToken, ErrorCode.ERR_ExpectedPPFile, isActive);
|
||
|
|
SyntaxToken endOfDirectiveToken = ParseEndOfDirective(((GreenNode)syntaxToken).IsMissing || !isActive);
|
||
|
|
return SyntaxFactory.LoadDirectiveTrivia(hash, keyword, syntaxToken, endOfDirectiveToken, isActive);
|
||
|
|
}
|
||
|
|
|
||
|
|
private DirectiveTriviaSyntax ParseNullableDirective(SyntaxToken hash, SyntaxToken token, bool isActive)
|
||
|
|
{
|
||
|
|
if (isActive)
|
||
|
|
{
|
||
|
|
token = CheckFeatureAvailability(token, MessageID.IDS_FeatureNullableReferenceTypes);
|
||
|
|
}
|
||
|
|
SyntaxToken syntaxToken = base.CurrentToken.Kind switch
|
||
|
|
{
|
||
|
|
SyntaxKind.EnableKeyword => EatToken(),
|
||
|
|
SyntaxKind.DisableKeyword => EatToken(),
|
||
|
|
SyntaxKind.RestoreKeyword => EatToken(),
|
||
|
|
_ => EatToken(SyntaxKind.DisableKeyword, ErrorCode.ERR_NullableDirectiveQualifierExpected, isActive),
|
||
|
|
};
|
||
|
|
SyntaxToken syntaxToken2 = base.CurrentToken.Kind switch
|
||
|
|
{
|
||
|
|
SyntaxKind.WarningsKeyword => EatToken(),
|
||
|
|
SyntaxKind.AnnotationsKeyword => EatToken(),
|
||
|
|
SyntaxKind.EndOfDirectiveToken => null,
|
||
|
|
SyntaxKind.EndOfFileToken => null,
|
||
|
|
_ => EatToken(SyntaxKind.WarningsKeyword, ErrorCode.ERR_NullableDirectiveTargetExpected, !((GreenNode)syntaxToken).IsMissing && isActive),
|
||
|
|
};
|
||
|
|
SyntaxToken endOfDirectiveToken = ParseEndOfDirective(((GreenNode)syntaxToken).IsMissing || (syntaxToken2 != null && ((GreenNode)syntaxToken2).IsMissing) || !isActive);
|
||
|
|
return SyntaxFactory.NullableDirectiveTrivia(hash, token, syntaxToken, syntaxToken2, endOfDirectiveToken, isActive);
|
||
|
|
}
|
||
|
|
|
||
|
|
private DirectiveTriviaSyntax ParsePragmaDirective(SyntaxToken hash, SyntaxToken pragma, bool isActive)
|
||
|
|
{
|
||
|
|
//IL_0300: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_0306: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_0179: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_017f: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_0148: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
if (isActive)
|
||
|
|
{
|
||
|
|
pragma = CheckFeatureAvailability(pragma, MessageID.IDS_FeaturePragma);
|
||
|
|
}
|
||
|
|
bool flag = false;
|
||
|
|
if (base.CurrentToken.ContextualKind == SyntaxKind.WarningKeyword)
|
||
|
|
{
|
||
|
|
SyntaxToken warningKeyword = EatContextualToken(SyntaxKind.WarningKeyword);
|
||
|
|
SyntaxToken disableOrRestoreKeyword;
|
||
|
|
if (base.CurrentToken.Kind == SyntaxKind.DisableKeyword || base.CurrentToken.Kind == SyntaxKind.RestoreKeyword)
|
||
|
|
{
|
||
|
|
disableOrRestoreKeyword = EatToken();
|
||
|
|
SeparatedSyntaxListBuilder<ExpressionSyntax> val = default(SeparatedSyntaxListBuilder<ExpressionSyntax>);
|
||
|
|
val._002Ector(10);
|
||
|
|
while (base.CurrentToken.Kind != SyntaxKind.EndOfDirectiveToken)
|
||
|
|
{
|
||
|
|
SyntaxToken syntaxToken;
|
||
|
|
ExpressionSyntax expressionSyntax;
|
||
|
|
if (base.CurrentToken.Kind == SyntaxKind.NumericLiteralToken)
|
||
|
|
{
|
||
|
|
syntaxToken = EatToken();
|
||
|
|
expressionSyntax = SyntaxFactory.LiteralExpression(SyntaxKind.NumericLiteralExpression, syntaxToken);
|
||
|
|
}
|
||
|
|
else if (base.CurrentToken.Kind == SyntaxKind.IdentifierToken)
|
||
|
|
{
|
||
|
|
syntaxToken = EatToken();
|
||
|
|
expressionSyntax = SyntaxFactory.IdentifierName(syntaxToken);
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
syntaxToken = EatToken(SyntaxKind.NumericLiteralToken, ErrorCode.WRN_IdentifierOrNumericLiteralExpected, isActive);
|
||
|
|
expressionSyntax = SyntaxFactory.LiteralExpression(SyntaxKind.NumericLiteralExpression, syntaxToken);
|
||
|
|
}
|
||
|
|
flag = flag || ((GreenNode)syntaxToken).ContainsDiagnostics;
|
||
|
|
val.Add(expressionSyntax);
|
||
|
|
if (base.CurrentToken.Kind != SyntaxKind.CommaToken)
|
||
|
|
{
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
val.AddSeparator((GreenNode)(object)EatToken());
|
||
|
|
}
|
||
|
|
SyntaxToken endOfDirectiveToken = ParseEndOfDirective(flag || !isActive, afterPragma: true);
|
||
|
|
return SyntaxFactory.PragmaWarningDirectiveTrivia(hash, pragma, warningKeyword, disableOrRestoreKeyword, val.ToList(), endOfDirectiveToken, isActive);
|
||
|
|
}
|
||
|
|
disableOrRestoreKeyword = EatToken(SyntaxKind.DisableKeyword, ErrorCode.WRN_IllegalPPWarning, isActive);
|
||
|
|
SyntaxToken endOfDirectiveToken2 = ParseEndOfDirective(ignoreErrors: true, afterPragma: true);
|
||
|
|
return SyntaxFactory.PragmaWarningDirectiveTrivia(hash, pragma, warningKeyword, disableOrRestoreKeyword, default(SeparatedSyntaxList<ExpressionSyntax>), endOfDirectiveToken2, isActive);
|
||
|
|
}
|
||
|
|
if (base.CurrentToken.Kind == SyntaxKind.ChecksumKeyword)
|
||
|
|
{
|
||
|
|
SyntaxToken checksumKeyword = EatToken();
|
||
|
|
SyntaxToken syntaxToken2 = EatToken(SyntaxKind.StringLiteralToken, ErrorCode.WRN_IllegalPPChecksum, isActive);
|
||
|
|
SyntaxToken syntaxToken3 = EatToken(SyntaxKind.StringLiteralToken, ErrorCode.WRN_IllegalPPChecksum, isActive && !((GreenNode)syntaxToken2).IsMissing);
|
||
|
|
if (isActive && !((GreenNode)syntaxToken3).IsMissing && !Guid.TryParse(syntaxToken3.ValueText, out var _))
|
||
|
|
{
|
||
|
|
syntaxToken3 = AddError(syntaxToken3, ErrorCode.WRN_IllegalPPChecksum);
|
||
|
|
}
|
||
|
|
SyntaxToken syntaxToken4 = EatToken(SyntaxKind.StringLiteralToken, ErrorCode.WRN_IllegalPPChecksum, isActive && !((GreenNode)syntaxToken3).IsMissing);
|
||
|
|
if (isActive && !((GreenNode)syntaxToken4).IsMissing)
|
||
|
|
{
|
||
|
|
if (syntaxToken4.ValueText.Length % 2 != 0)
|
||
|
|
{
|
||
|
|
syntaxToken4 = AddError(syntaxToken4, ErrorCode.WRN_IllegalPPChecksum);
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
string valueText = syntaxToken4.ValueText;
|
||
|
|
for (int i = 0; i < valueText.Length; i++)
|
||
|
|
{
|
||
|
|
if (!SyntaxFacts.IsHexDigit(valueText[i]))
|
||
|
|
{
|
||
|
|
syntaxToken4 = AddError(syntaxToken4, ErrorCode.WRN_IllegalPPChecksum);
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
flag = ((GreenNode)syntaxToken2).ContainsDiagnostics | ((GreenNode)syntaxToken3).ContainsDiagnostics | ((GreenNode)syntaxToken4).ContainsDiagnostics;
|
||
|
|
SyntaxToken endOfDirectiveToken3 = ParseEndOfDirective(flag, afterPragma: true);
|
||
|
|
return SyntaxFactory.PragmaChecksumDirectiveTrivia(hash, pragma, checksumKeyword, syntaxToken2, syntaxToken3, syntaxToken4, endOfDirectiveToken3, isActive);
|
||
|
|
}
|
||
|
|
SyntaxToken warningKeyword2 = EatToken(SyntaxKind.WarningKeyword, ErrorCode.WRN_IllegalPragma, isActive);
|
||
|
|
SyntaxToken disableOrRestoreKeyword2 = EatToken(SyntaxKind.DisableKeyword, reportError: false);
|
||
|
|
SyntaxToken endOfDirectiveToken4 = ParseEndOfDirective(ignoreErrors: true, afterPragma: true);
|
||
|
|
return SyntaxFactory.PragmaWarningDirectiveTrivia(hash, pragma, warningKeyword2, disableOrRestoreKeyword2, default(SeparatedSyntaxList<ExpressionSyntax>), endOfDirectiveToken4, isActive);
|
||
|
|
}
|
||
|
|
|
||
|
|
private DirectiveTriviaSyntax ParseShebangDirective(SyntaxToken hash, SyntaxToken exclamation, bool isActive)
|
||
|
|
{
|
||
|
|
return SyntaxFactory.ShebangDirectiveTrivia(hash, exclamation, ParseEndOfDirectiveWithOptionalPreprocessingMessage(), isActive);
|
||
|
|
}
|
||
|
|
|
||
|
|
private SyntaxToken ParseEndOfDirectiveWithOptionalPreprocessingMessage()
|
||
|
|
{
|
||
|
|
return lexer.LexEndOfDirectiveWithOptionalPreprocessingMessage();
|
||
|
|
}
|
||
|
|
|
||
|
|
private SyntaxToken ParseEndOfDirective(bool ignoreErrors, bool afterPragma = false, bool afterLineNumber = false)
|
||
|
|
{
|
||
|
|
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_007e: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_0069: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
SyntaxListBuilder<SyntaxToken> val = default(SyntaxListBuilder<SyntaxToken>);
|
||
|
|
if (base.CurrentToken.Kind != SyntaxKind.EndOfDirectiveToken && base.CurrentToken.Kind != SyntaxKind.EndOfFileToken)
|
||
|
|
{
|
||
|
|
val._002Ector(10);
|
||
|
|
if (!ignoreErrors)
|
||
|
|
{
|
||
|
|
ErrorCode code = ErrorCode.ERR_EndOfPPLineExpected;
|
||
|
|
if (afterPragma)
|
||
|
|
{
|
||
|
|
code = ErrorCode.WRN_EndOfPPLineExpected;
|
||
|
|
}
|
||
|
|
else if (afterLineNumber)
|
||
|
|
{
|
||
|
|
code = ErrorCode.ERR_MissingPPFile;
|
||
|
|
}
|
||
|
|
val.Add(AddError(GreenNodeExtensions.WithoutDiagnosticsGreen<SyntaxToken>(EatToken()), code));
|
||
|
|
}
|
||
|
|
while (base.CurrentToken.Kind != SyntaxKind.EndOfDirectiveToken && base.CurrentToken.Kind != SyntaxKind.EndOfFileToken)
|
||
|
|
{
|
||
|
|
val.Add(GreenNodeExtensions.WithoutDiagnosticsGreen<SyntaxToken>(EatToken()));
|
||
|
|
}
|
||
|
|
}
|
||
|
|
SyntaxToken syntaxToken = ((base.CurrentToken.Kind == SyntaxKind.EndOfDirectiveToken) ? EatToken() : SyntaxFactory.Token(SyntaxKind.EndOfDirectiveToken));
|
||
|
|
if (!val.IsNull)
|
||
|
|
{
|
||
|
|
syntaxToken = syntaxToken.TokenWithLeadingTrivia((GreenNode)(object)SyntaxFactory.SkippedTokensTrivia(val.ToList()));
|
||
|
|
}
|
||
|
|
return syntaxToken;
|
||
|
|
}
|
||
|
|
|
||
|
|
private ExpressionSyntax ParseExpression()
|
||
|
|
{
|
||
|
|
return ParseLogicalOr();
|
||
|
|
}
|
||
|
|
|
||
|
|
private ExpressionSyntax ParseLogicalOr()
|
||
|
|
{
|
||
|
|
ExpressionSyntax expressionSyntax = ParseLogicalAnd();
|
||
|
|
while (base.CurrentToken.Kind == SyntaxKind.BarBarToken)
|
||
|
|
{
|
||
|
|
SyntaxToken operatorToken = EatToken();
|
||
|
|
ExpressionSyntax right = ParseLogicalAnd();
|
||
|
|
expressionSyntax = SyntaxFactory.BinaryExpression(SyntaxKind.LogicalOrExpression, expressionSyntax, operatorToken, right);
|
||
|
|
}
|
||
|
|
return expressionSyntax;
|
||
|
|
}
|
||
|
|
|
||
|
|
private ExpressionSyntax ParseLogicalAnd()
|
||
|
|
{
|
||
|
|
ExpressionSyntax expressionSyntax = ParseEquality();
|
||
|
|
while (base.CurrentToken.Kind == SyntaxKind.AmpersandAmpersandToken)
|
||
|
|
{
|
||
|
|
SyntaxToken operatorToken = EatToken();
|
||
|
|
ExpressionSyntax right = ParseEquality();
|
||
|
|
expressionSyntax = SyntaxFactory.BinaryExpression(SyntaxKind.LogicalAndExpression, expressionSyntax, operatorToken, right);
|
||
|
|
}
|
||
|
|
return expressionSyntax;
|
||
|
|
}
|
||
|
|
|
||
|
|
private ExpressionSyntax ParseEquality()
|
||
|
|
{
|
||
|
|
ExpressionSyntax expressionSyntax = ParseLogicalNot();
|
||
|
|
while (base.CurrentToken.Kind == SyntaxKind.EqualsEqualsToken || base.CurrentToken.Kind == SyntaxKind.ExclamationEqualsToken)
|
||
|
|
{
|
||
|
|
SyntaxToken syntaxToken = EatToken();
|
||
|
|
ExpressionSyntax right = ParseEquality();
|
||
|
|
expressionSyntax = SyntaxFactory.BinaryExpression(SyntaxFacts.GetBinaryExpression(syntaxToken.Kind), expressionSyntax, syntaxToken, right);
|
||
|
|
}
|
||
|
|
return expressionSyntax;
|
||
|
|
}
|
||
|
|
|
||
|
|
private ExpressionSyntax ParseLogicalNot()
|
||
|
|
{
|
||
|
|
if (base.CurrentToken.Kind == SyntaxKind.ExclamationToken)
|
||
|
|
{
|
||
|
|
SyntaxToken operatorToken = EatToken();
|
||
|
|
return SyntaxFactory.PrefixUnaryExpression(SyntaxKind.LogicalNotExpression, operatorToken, ParseLogicalNot());
|
||
|
|
}
|
||
|
|
return ParsePrimary();
|
||
|
|
}
|
||
|
|
|
||
|
|
private ExpressionSyntax ParsePrimary()
|
||
|
|
{
|
||
|
|
SyntaxKind kind = base.CurrentToken.Kind;
|
||
|
|
switch (kind)
|
||
|
|
{
|
||
|
|
case SyntaxKind.OpenParenToken:
|
||
|
|
{
|
||
|
|
SyntaxToken openParenToken = EatToken();
|
||
|
|
ExpressionSyntax expression = ParseExpression();
|
||
|
|
SyntaxToken closeParenToken = EatToken(SyntaxKind.CloseParenToken);
|
||
|
|
return SyntaxFactory.ParenthesizedExpression(openParenToken, expression, closeParenToken);
|
||
|
|
}
|
||
|
|
case SyntaxKind.IdentifierToken:
|
||
|
|
return SyntaxFactory.IdentifierName(TruncateIdentifier(EatToken()));
|
||
|
|
case SyntaxKind.TrueKeyword:
|
||
|
|
case SyntaxKind.FalseKeyword:
|
||
|
|
return SyntaxFactory.LiteralExpression(SyntaxFacts.GetLiteralExpression(kind), EatToken());
|
||
|
|
default:
|
||
|
|
return SyntaxFactory.IdentifierName(EatToken(SyntaxKind.IdentifierToken, ErrorCode.ERR_InvalidPreprocExpr));
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private static SyntaxToken TruncateIdentifier(SyntaxToken identifier)
|
||
|
|
{
|
||
|
|
if (((GreenNode)identifier).Width > 128)
|
||
|
|
{
|
||
|
|
GreenNode leadingTrivia = identifier.GetLeadingTrivia();
|
||
|
|
GreenNode trailingTrivia = identifier.GetTrailingTrivia();
|
||
|
|
string text = ((object)identifier).ToString();
|
||
|
|
string valueText = text.Substring(0, 128);
|
||
|
|
identifier = SyntaxFactory.Identifier(SyntaxKind.IdentifierToken, leadingTrivia, text, valueText, trailingTrivia);
|
||
|
|
}
|
||
|
|
return identifier;
|
||
|
|
}
|
||
|
|
|
||
|
|
private bool EvaluateBool(ExpressionSyntax expr)
|
||
|
|
{
|
||
|
|
object obj = Evaluate(expr);
|
||
|
|
if (obj is bool)
|
||
|
|
{
|
||
|
|
return (bool)obj;
|
||
|
|
}
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
private object Evaluate(ExpressionSyntax expr)
|
||
|
|
{
|
||
|
|
switch (expr.Kind)
|
||
|
|
{
|
||
|
|
case SyntaxKind.ParenthesizedExpression:
|
||
|
|
return Evaluate(((ParenthesizedExpressionSyntax)expr).Expression);
|
||
|
|
case SyntaxKind.TrueLiteralExpression:
|
||
|
|
case SyntaxKind.FalseLiteralExpression:
|
||
|
|
return ((LiteralExpressionSyntax)expr).Token.Value;
|
||
|
|
case SyntaxKind.LogicalAndExpression:
|
||
|
|
case SyntaxKind.BitwiseAndExpression:
|
||
|
|
return EvaluateBool(((BinaryExpressionSyntax)expr).Left) && EvaluateBool(((BinaryExpressionSyntax)expr).Right);
|
||
|
|
case SyntaxKind.LogicalOrExpression:
|
||
|
|
case SyntaxKind.BitwiseOrExpression:
|
||
|
|
return EvaluateBool(((BinaryExpressionSyntax)expr).Left) || EvaluateBool(((BinaryExpressionSyntax)expr).Right);
|
||
|
|
case SyntaxKind.EqualsExpression:
|
||
|
|
return object.Equals(Evaluate(((BinaryExpressionSyntax)expr).Left), Evaluate(((BinaryExpressionSyntax)expr).Right));
|
||
|
|
case SyntaxKind.NotEqualsExpression:
|
||
|
|
return !object.Equals(Evaluate(((BinaryExpressionSyntax)expr).Left), Evaluate(((BinaryExpressionSyntax)expr).Right));
|
||
|
|
case SyntaxKind.LogicalNotExpression:
|
||
|
|
return !EvaluateBool(((PrefixUnaryExpressionSyntax)expr).Operand);
|
||
|
|
case SyntaxKind.IdentifierName:
|
||
|
|
{
|
||
|
|
string valueText = ((IdentifierNameSyntax)expr).Identifier.ValueText;
|
||
|
|
if (bool.TryParse(valueText, out var result))
|
||
|
|
{
|
||
|
|
return result;
|
||
|
|
}
|
||
|
|
return IsDefined(valueText);
|
||
|
|
}
|
||
|
|
default:
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private bool IsDefined(string id)
|
||
|
|
{
|
||
|
|
return _context.IsDefined(id) switch
|
||
|
|
{
|
||
|
|
DefineState.Defined => true,
|
||
|
|
DefineState.Undefined => false,
|
||
|
|
_ => base.Options.PreprocessorSymbols.Contains(id),
|
||
|
|
};
|
||
|
|
}
|
||
|
|
}
|