Use nullable reference types in Parser

This commit is contained in:
Alexander Luzgarev 2018-12-22 22:04:45 +01:00
parent c361b8e004
commit 198042fabc
34 changed files with 900 additions and 641 deletions

View File

@ -196,6 +196,11 @@ namespace ProjectConsole
Visit(node.InputDescription); Visit(node.InputDescription);
Visit(node.Commas); Visit(node.Commas);
Visit(node.Body); Visit(node.Body);
Visit(node.EndKeyword);
}
public override void VisitEndKeyword(EndKeywordSyntaxNode node)
{
OutputKeyword(node.EndKeyword); OutputKeyword(node.EndKeyword);
} }
@ -207,7 +212,7 @@ namespace ProjectConsole
Visit(node.InputDescription); Visit(node.InputDescription);
Visit(node.Commas); Visit(node.Commas);
Visit(node.Body); Visit(node.Body);
OutputKeyword(node.EndKeyword); Visit(node.EndKeyword);
} }
public override void VisitIfStatement(IfStatementSyntaxNode node) public override void VisitIfStatement(IfStatementSyntaxNode node)

View File

@ -68,7 +68,7 @@ namespace Parser
internal SyntaxNodeOrToken ThisInternal(int index) internal SyntaxNodeOrToken ThisInternal(int index)
{ {
var currentSlotIndex = 0; var currentSlotIndex = 0;
GreenNode currentSlot = null; GreenNode? currentSlot = null;
while (true) while (true)
{ {
currentSlot = _node._green.GetSlot(currentSlotIndex); currentSlot = _node._green.GetSlot(currentSlotIndex);
@ -84,13 +84,17 @@ namespace Parser
if (currentSlot.IsList) if (currentSlot.IsList)
{ {
var listSlot = _node.GetNode(currentSlotIndex); var listSlot = _node.GetNode(currentSlotIndex);
if (listSlot is null)
{
throw new Exception($"Unexpected null in list slot.");
}
var red = listSlot.GetNode(index); var red = listSlot.GetNode(index);
if (red != null) if (!(red is null))
{ {
return red; return red;
} }
// this is a token // this is a token
return new SyntaxToken(listSlot, listSlot._green.GetSlot(index), _node.GetChildPosition(index)); return new SyntaxToken(listSlot, listSlot._green.GetSlot(index)!, _node.GetChildPosition(index));
} }
else else
{ {
@ -100,7 +104,7 @@ namespace Parser
return red; return red;
} }
// this is a token // this is a token
return new SyntaxToken(_node, _node._green.GetSlot(currentSlotIndex), _node.GetChildPosition(currentSlotIndex)); return new SyntaxToken(_node, _node._green.GetSlot(currentSlotIndex)!, _node.GetChildPosition(currentSlotIndex));
} }
} }

View File

@ -4,7 +4,7 @@ namespace Parser.Internal
{ {
public class Diagnostic public class Diagnostic
{ {
public TextSpan Span { get; } public TextSpan? Span { get; }
public string Message { get; } public string Message { get; }
public Diagnostic(TextSpan span, string message) public Diagnostic(TextSpan span, string message)
@ -12,5 +12,10 @@ namespace Parser.Internal
Span = span; Span = span;
Message = message ?? throw new ArgumentNullException(nameof(message)); Message = message ?? throw new ArgumentNullException(nameof(message));
} }
public Diagnostic(string message)
{
Message = message ?? throw new ArgumentNullException(nameof(message));
}
} }
} }

View File

@ -26,6 +26,12 @@ namespace Parser.Internal
_diagnostics.Add(diagnostic); _diagnostics.Add(diagnostic);
} }
private void Report(string message)
{
var diagnostic = new Diagnostic(message);
_diagnostics.Add(diagnostic);
}
internal void ReportUnexpectedEndOfFile(TextSpan span) internal void ReportUnexpectedEndOfFile(TextSpan span)
{ {
Report(span, "Unexpected end of file."); Report(span, "Unexpected end of file.");
@ -46,9 +52,9 @@ namespace Parser.Internal
Report(span, $"Unknown symbol '{c}'."); Report(span, $"Unknown symbol '{c}'.");
} }
internal void ReportUnexpectedToken(TextSpan span, TokenKind expected, TokenKind actual) internal void ReportUnexpectedToken(TokenKind expected, TokenKind actual)
{ {
Report(span, $"Unexpected token '{actual}', expected '{expected}'."); Report($"Unexpected token '{actual}', expected '{expected}'.");
} }
public IEnumerator<Diagnostic> GetEnumerator() public IEnumerator<Diagnostic> GetEnumerator()

View File

@ -10,7 +10,7 @@ namespace Parser.Internal
{ {
public TokenKind Kind { get; } public TokenKind Kind { get; }
public int Slots { get; protected set; } public int Slots { get; protected set; }
public abstract GreenNode GetSlot(int i); public abstract GreenNode? GetSlot(int i);
public GreenNode(TokenKind kind) public GreenNode(TokenKind kind)
{ {
@ -29,7 +29,7 @@ namespace Parser.Internal
public int FullWidth => _fullWidth; public int FullWidth => _fullWidth;
protected void AdjustWidth(GreenNode node) protected void AdjustWidth(GreenNode? node)
{ {
if (!(node is null)) if (!(node is null))
{ {
@ -109,12 +109,12 @@ namespace Parser.Internal
return -1; return -1;
} }
private GreenNode GetFirstTerminal() private GreenNode? GetFirstTerminal()
{ {
var current = this; var current = this;
while (true) while (true)
{ {
GreenNode next = null; GreenNode? next = null;
if (current.Slots == 0) if (current.Slots == 0)
{ {
return current; return current;
@ -141,12 +141,12 @@ namespace Parser.Internal
} }
} }
private GreenNode GetLastTerminal() private GreenNode? GetLastTerminal()
{ {
var current = this; var current = this;
while (true) while (true)
{ {
GreenNode next = null; GreenNode? next = null;
if (current.Slots == 0) if (current.Slots == 0)
{ {
return current; return current;

View File

@ -9,9 +9,9 @@ namespace Parser.Internal
{ {
private class TokenInfo private class TokenInfo
{ {
public TokenKind Kind { get; set; } public TokenKind Kind { get; set; } = TokenKind.None;
public string Text { get; set; } public string Text { get; set; } = "";
public string StringValue { get; set; } public string StringValue { get; set; } = "";
public double DoubleValue { get; set; } public double DoubleValue { get; set; }
} }
@ -25,6 +25,7 @@ namespace Parser.Internal
public MLexerGreen(ITextWindow window) public MLexerGreen(ITextWindow window)
{ {
Window = window; Window = window;
LastToken = SyntaxToken.NoneToken;
TokenStack = new Stack<TokenKind>(); TokenStack = new Stack<TokenKind>();
} }

View File

@ -33,7 +33,7 @@ namespace Parser.Internal
var token = CurrentToken; var token = CurrentToken;
if (token.Kind != kind) if (token.Kind != kind)
{ {
Diagnostics.ReportUnexpectedToken(token.Span, kind, token.Kind); Diagnostics.ReportUnexpectedToken(kind, token.Kind);
return TokenFactory.CreateMissing(kind, null, null); return TokenFactory.CreateMissing(kind, null, null);
} }
_index++; _index++;
@ -55,13 +55,13 @@ namespace Parser.Internal
var token = CurrentToken; var token = CurrentToken;
if (token.Kind != TokenKind.IdentifierToken) if (token.Kind != TokenKind.IdentifierToken)
{ {
Diagnostics.ReportUnexpectedToken(token.Span, TokenKind.IdentifierToken, token.Kind); Diagnostics.ReportUnexpectedToken(TokenKind.IdentifierToken, token.Kind);
return TokenFactory.CreateMissing(TokenKind.IdentifierToken, null, null); return TokenFactory.CreateMissing(TokenKind.IdentifierToken, null, null);
} }
if (token.Text != s) if (token.Text != s)
{ {
Diagnostics.ReportUnexpectedToken(token.Span, TokenKind.IdentifierToken, token.Kind); Diagnostics.ReportUnexpectedToken(TokenKind.IdentifierToken, token.Kind);
return TokenFactory.CreateMissing(TokenKind.IdentifierToken, null, null); return TokenFactory.CreateMissing(TokenKind.IdentifierToken, null, null);
} }
@ -69,7 +69,7 @@ namespace Parser.Internal
return token; return token;
} }
private SyntaxToken PossiblyEatIdentifier(string s) private SyntaxToken? PossiblyEatIdentifier(string s)
{ {
var token = CurrentToken; var token = CurrentToken;
if (token.Kind == TokenKind.IdentifierToken && token.Text == s) if (token.Kind == TokenKind.IdentifierToken && token.Text == s)
@ -94,7 +94,7 @@ namespace Parser.Internal
new List<SyntaxTrivia>()); new List<SyntaxTrivia>());
} }
private SyntaxList ParseFunctionOutputList() private SyntaxList? ParseFunctionOutputList()
{ {
var outputs = new SyntaxListBuilder(); var outputs = new SyntaxListBuilder();
var firstToken = true; var firstToken = true;
@ -112,7 +112,7 @@ namespace Parser.Internal
return outputs.ToList(); return outputs.ToList();
} }
private FunctionOutputDescriptionSyntaxNode ParseFunctionOutputDescription() private FunctionOutputDescriptionSyntaxNode? ParseFunctionOutputDescription()
{ {
SyntaxToken assignmentSign; SyntaxToken assignmentSign;
var builder = new SyntaxListBuilder(); var builder = new SyntaxListBuilder();
@ -180,7 +180,7 @@ namespace Parser.Internal
return builder.ToList(); return builder.ToList();
} }
private FunctionInputDescriptionSyntaxNode ParseFunctionInputDescription() private FunctionInputDescriptionSyntaxNode? ParseFunctionInputDescription()
{ {
if (CurrentToken.Kind == TokenKind.OpenParenthesisToken) if (CurrentToken.Kind == TokenKind.OpenParenthesisToken)
{ {
@ -206,7 +206,8 @@ namespace Parser.Internal
var inputDescription = ParseFunctionInputDescription(); var inputDescription = ParseFunctionInputDescription();
var commas = ParseOptionalCommas(); var commas = ParseOptionalCommas();
var body = ParseStatementList(); var body = ParseStatementList();
var endKeyword = EatPossiblyMissingIdentifier("end"); var endKeyword = ParseEndKeyword();
//var endKeyword =
return Factory.FunctionDeclarationSyntax( return Factory.FunctionDeclarationSyntax(
functionKeyword, functionKeyword,
outputDescription, outputDescription,
@ -217,6 +218,12 @@ namespace Parser.Internal
endKeyword); endKeyword);
} }
private EndKeywordSyntaxNode? ParseEndKeyword()
{
var keyword = EatPossiblyMissingIdentifier("end");
return keyword is null ? null : Factory.EndKeywordSyntax(keyword);
}
internal struct ParseOptions internal struct ParseOptions
{ {
public bool ParsingArrayElements { get; set; } public bool ParsingArrayElements { get; set; }
@ -224,12 +231,12 @@ namespace Parser.Internal
public static ParseOptions Default = new ParseOptions { ParsingArrayElements = false }; public static ParseOptions Default = new ParseOptions { ParsingArrayElements = false };
} }
private ExpressionSyntaxNode ParseExpression() private ExpressionSyntaxNode? ParseExpression()
{ {
return ParseExpression(ParseOptions.Default); return ParseExpression(ParseOptions.Default);
} }
private ExpressionSyntaxNode ParseExpression(ParseOptions options) private ExpressionSyntaxNode? ParseExpression(ParseOptions options)
{ {
return ParseSubExpression(options, SyntaxFacts.Precedence.Expression); return ParseSubExpression(options, SyntaxFacts.Precedence.Expression);
} }
@ -286,10 +293,10 @@ namespace Parser.Internal
return builder.ToList(); return builder.ToList();
} }
private ExpressionSyntaxNode ParseTerm(ParseOptions options) private ExpressionSyntaxNode? ParseTerm(ParseOptions options)
{ {
var token = CurrentToken; var token = CurrentToken;
ExpressionSyntaxNode expression = null; ExpressionSyntaxNode? expression = null;
switch (token.Kind) switch (token.Kind)
{ {
case TokenKind.NumberLiteralToken: case TokenKind.NumberLiteralToken:
@ -410,6 +417,11 @@ namespace Parser.Internal
return Factory.CommandExpressionSyntax(idNameNode, builder.ToList()); return Factory.CommandExpressionSyntax(idNameNode, builder.ToList());
} }
if (expression is null)
{
throw new Exception("Command expression identifier cannot be empty.");
}
throw new ParsingException($"Unexpected token \"{CurrentToken}\" while parsing expression \"{expression.FullText}\" at {CurrentPosition}."); throw new ParsingException($"Unexpected token \"{CurrentToken}\" while parsing expression \"{expression.FullText}\" at {CurrentPosition}.");
} }
@ -420,6 +432,10 @@ namespace Parser.Internal
{ {
var atToken = EatToken(); var atToken = EatToken();
var baseClassNameWithArguments = ParseExpression(); var baseClassNameWithArguments = ParseExpression();
if (baseClassNameWithArguments is null)
{
throw new Exception($"Base class name cannot be empty.");
}
return Factory.BaseClassInvokationSyntax(methodName, atToken, baseClassNameWithArguments); return Factory.BaseClassInvokationSyntax(methodName, atToken, baseClassNameWithArguments);
} }
if (expression is MemberAccessSyntaxNode memberAccess if (expression is MemberAccessSyntaxNode memberAccess
@ -427,6 +443,10 @@ namespace Parser.Internal
{ {
var atToken = EatToken(); var atToken = EatToken();
var baseClassNameWithArguments = ParseExpression(); var baseClassNameWithArguments = ParseExpression();
if (baseClassNameWithArguments is null)
{
throw new Exception($"Base class name cannot be empty.");
}
return Factory.BaseClassInvokationSyntax(memberAccess, atToken, baseClassNameWithArguments); return Factory.BaseClassInvokationSyntax(memberAccess, atToken, baseClassNameWithArguments);
} }
throw new ParsingException($"Unexpected token \"{CurrentToken}\" at {CurrentPosition}."); throw new ParsingException($"Unexpected token \"{CurrentToken}\" at {CurrentPosition}.");
@ -442,6 +462,10 @@ namespace Parser.Internal
{ {
var openingBracket = EatToken(); var openingBracket = EatToken();
var indirectMember = ParseExpression(); var indirectMember = ParseExpression();
if (indirectMember is null)
{
throw new Exception("Indirect member invokation cannot be empty.");
}
var closingBracket = EatToken(TokenKind.CloseParenthesisToken); var closingBracket = EatToken(TokenKind.CloseParenthesisToken);
return Factory.IndirectMemberAccessSyntax( return Factory.IndirectMemberAccessSyntax(
openingBracket, openingBracket,
@ -466,7 +490,12 @@ namespace Parser.Internal
firstToken = false; firstToken = false;
} }
builder.Add(ParseExpression()); var expression = ParseExpression();
if (expression is null)
{
throw new Exception("Function call parameter cannot be empty.");
}
builder.Add(expression);
} }
return builder.ToList(); return builder.ToList();
@ -476,6 +505,10 @@ namespace Parser.Internal
{ {
var openParen = EatToken(TokenKind.OpenParenthesisToken); var openParen = EatToken(TokenKind.OpenParenthesisToken);
var expression = ParseExpression(); var expression = ParseExpression();
if (expression is null)
{
throw new Exception("Parenthesized expression cannot be empty.");
}
var closeParen = EatToken(TokenKind.CloseParenthesisToken); var closeParen = EatToken(TokenKind.CloseParenthesisToken);
return Factory.ParenthesizedExpressionSyntax( return Factory.ParenthesizedExpressionSyntax(
openParen, openParen,
@ -514,17 +547,25 @@ namespace Parser.Internal
else if (CurrentToken.Kind == TokenKind.OpenParenthesisToken) else if (CurrentToken.Kind == TokenKind.OpenParenthesisToken)
{ {
var inputs = ParseFunctionInputDescription(); var inputs = ParseFunctionInputDescription();
if (inputs is null)
{
throw new Exception($"Lambda expression inputs cannot be empty.");
}
var body = ParseExpression(); var body = ParseExpression();
if (body is null)
{
throw new Exception($"Lambda expression body cannot be empty.");
}
return Factory.LambdaSyntax(atSign, inputs, body); return Factory.LambdaSyntax(atSign, inputs, body);
} }
throw new ParsingException($"Unexpected token {CurrentToken} while parsing function handle at {CurrentPosition}."); throw new ParsingException($"Unexpected token {CurrentToken} while parsing function handle at {CurrentPosition}.");
} }
private ExpressionSyntaxNode ParseSubExpression( private ExpressionSyntaxNode? ParseSubExpression(
ParseOptions options, ParseOptions options,
SyntaxFacts.Precedence precedence) SyntaxFacts.Precedence precedence)
{ {
ExpressionSyntaxNode lhs; ExpressionSyntaxNode? lhs;
if (SyntaxFacts.IsUnaryOperator(CurrentToken.Kind)) if (SyntaxFacts.IsUnaryOperator(CurrentToken.Kind))
{ {
var operation = EatToken(); var operation = EatToken();
@ -551,6 +592,10 @@ namespace Parser.Internal
else else
{ {
lhs = ParseTerm(options); lhs = ParseTerm(options);
if (lhs is null)
{
throw new Exception("Left-hand side in subexpression cannot be empty.");
}
} }
while (true) while (true)
@ -579,9 +624,10 @@ namespace Parser.Internal
} }
else else
{ {
rhs = null; throw new Exception("Right-hand side in subexpression cannot be empty.");
} }
} }
if (token.Kind == TokenKind.EqualsToken) if (token.Kind == TokenKind.EqualsToken)
{ {
lhs = Factory.AssignmentExpressionSyntax(lhs, token, rhs); lhs = Factory.AssignmentExpressionSyntax(lhs, token, rhs);
@ -627,6 +673,10 @@ namespace Parser.Internal
{ {
var caseKeyword = EatIdentifier("case"); var caseKeyword = EatIdentifier("case");
var caseId = ParseExpression(); var caseId = ParseExpression();
if (caseId is null)
{
throw new Exception("Case label cannot be empty.");
}
var commas = ParseOptionalCommas(); var commas = ParseOptionalCommas();
var statementList = ParseStatementList(); var statementList = ParseStatementList();
return Factory.SwitchCaseSyntax(caseKeyword, caseId, commas, statementList); return Factory.SwitchCaseSyntax(caseKeyword, caseId, commas, statementList);
@ -636,6 +686,10 @@ namespace Parser.Internal
{ {
var switchKeyword = EatIdentifier("switch"); var switchKeyword = EatIdentifier("switch");
var expression = ParseExpression(); var expression = ParseExpression();
if (expression is null)
{
throw new Exception("Match expression in switch statement cannot be empty.");
}
var commas = ParseOptionalCommas(); var commas = ParseOptionalCommas();
var builder = new SyntaxListBuilder<SwitchCaseSyntaxNode>(); var builder = new SyntaxListBuilder<SwitchCaseSyntaxNode>();
while (IsIdentifier(CurrentToken, "case")) while (IsIdentifier(CurrentToken, "case"))
@ -655,6 +709,11 @@ namespace Parser.Internal
{ {
var whileKeyword = EatIdentifier("while"); var whileKeyword = EatIdentifier("while");
var condition = ParseExpression(); var condition = ParseExpression();
if (condition is null)
{
throw new Exception("Condition in while statement cannot be empty.");
}
var commas = ParseOptionalCommas(); var commas = ParseOptionalCommas();
var body = ParseStatementList(); var body = ParseStatementList();
var endKeyword = EatIdentifier("end"); var endKeyword = EatIdentifier("end");
@ -670,6 +729,10 @@ namespace Parser.Internal
{ {
var elseifKeyword = EatIdentifier("elseif"); var elseifKeyword = EatIdentifier("elseif");
var condition = ParseExpression(); var condition = ParseExpression();
if (condition is null)
{
throw new Exception("Condition in elseif clause cannot be empty.");
}
var commas = ParseOptionalCommas(); var commas = ParseOptionalCommas();
var body = ParseStatementList(); var body = ParseStatementList();
return Factory.ElseifClause(elseifKeyword, condition, commas, body); return Factory.ElseifClause(elseifKeyword, condition, commas, body);
@ -686,10 +749,14 @@ namespace Parser.Internal
{ {
var ifKeyword = EatIdentifier(); var ifKeyword = EatIdentifier();
var condition = ParseExpression(); var condition = ParseExpression();
if (condition is null)
{
throw new Exception("Condition in if statement cannot be empty.");
}
var commas = ParseOptionalSemicolonsOrCommas(); var commas = ParseOptionalSemicolonsOrCommas();
var body = ParseStatementList(); var body = ParseStatementList();
var elseifClauses = new SyntaxListBuilder<ElseifClause>(); var elseifClauses = new SyntaxListBuilder<ElseifClause>();
ElseClause elseClause = null; ElseClause? elseClause = null;
while (true) while (true)
{ {
var token = CurrentToken; var token = CurrentToken;
@ -740,7 +807,7 @@ namespace Parser.Internal
endKeyword); endKeyword);
} }
private CatchClauseSyntaxNode ParseCatchClause() private CatchClauseSyntaxNode? ParseCatchClause()
{ {
if (IsIdentifier(CurrentToken, "catch")) if (IsIdentifier(CurrentToken, "catch"))
{ {
@ -766,15 +833,24 @@ namespace Parser.Internal
private ExpressionStatementSyntaxNode ParseExpressionStatement() private ExpressionStatementSyntaxNode ParseExpressionStatement()
{ {
var expression = ParseExpression(); var expression = ParseExpression();
if (expression is null)
{
throw new Exception("Expression statement cannot be empty.");
}
return Factory.ExpressionStatementSyntax(expression); return Factory.ExpressionStatementSyntax(expression);
} }
private AttributeAssignmentSyntaxNode ParseAttributeAssignment() private AttributeAssignmentSyntaxNode? ParseAttributeAssignment()
{ {
if (CurrentToken.Kind == TokenKind.EqualsToken) if (CurrentToken.Kind == TokenKind.EqualsToken)
{ {
var assignmentSign = EatToken(); var assignmentSign = EatToken();
var value = ParseExpression(); var value = ParseExpression();
if (value is null)
{
throw new Exception("Right-hand side in attribute assignment cannot be empty.");
}
return Factory.AttributeAssignmentSyntax(assignmentSign, value); return Factory.AttributeAssignmentSyntax(assignmentSign, value);
} }
@ -845,7 +921,7 @@ namespace Parser.Internal
var inputDescription = ParseFunctionInputDescription(); var inputDescription = ParseFunctionInputDescription();
var commas = ParseOptionalCommas(); var commas = ParseOptionalCommas();
var body = ParseStatementList(); var body = ParseStatementList();
var endKeyword = PossiblyEatIdentifier("end"); var endKeyword = ParseEndKeyword();
return Factory.MethodDefinitionSyntax( return Factory.MethodDefinitionSyntax(
functionKeyword, functionKeyword,
outputDescription, outputDescription,
@ -859,7 +935,7 @@ namespace Parser.Internal
private MethodsListSyntaxNode ParseMethods() private MethodsListSyntaxNode ParseMethods()
{ {
var methodsKeyword = EatToken(); var methodsKeyword = EatToken();
AttributeListSyntaxNode attributes = null; AttributeListSyntaxNode? attributes = null;
if (CurrentToken.Kind == TokenKind.OpenParenthesisToken) if (CurrentToken.Kind == TokenKind.OpenParenthesisToken)
{ {
attributes = ParseAttributesList(); attributes = ParseAttributesList();
@ -876,7 +952,7 @@ namespace Parser.Internal
return Factory.MethodsListSyntax(methodsKeyword, attributes, builder.ToList(), endKeyword); return Factory.MethodsListSyntax(methodsKeyword, attributes, builder.ToList(), endKeyword);
} }
private GreenNode ParsePropertyDeclaration() private GreenNode? ParsePropertyDeclaration()
{ {
if (CurrentToken.Kind == TokenKind.CommaToken) if (CurrentToken.Kind == TokenKind.CommaToken)
{ {
@ -885,7 +961,7 @@ namespace Parser.Internal
return ParseStatement(); return ParseStatement();
} }
private SyntaxNode ParseEventDeclaration() private SyntaxNode? ParseEventDeclaration()
{ {
return ParseStatement(); return ParseStatement();
} }
@ -893,7 +969,7 @@ namespace Parser.Internal
private PropertiesListSyntaxNode ParseProperties() private PropertiesListSyntaxNode ParseProperties()
{ {
var propertiesKeyword = EatToken(); var propertiesKeyword = EatToken();
AttributeListSyntaxNode attributes = null; AttributeListSyntaxNode? attributes = null;
if (CurrentToken.Kind == TokenKind.OpenParenthesisToken) if (CurrentToken.Kind == TokenKind.OpenParenthesisToken)
{ {
attributes = ParseAttributesList(); attributes = ParseAttributesList();
@ -902,14 +978,19 @@ namespace Parser.Internal
var builder = new SyntaxListBuilder(); var builder = new SyntaxListBuilder();
while (!IsIdentifier(CurrentToken, "end")) while (!IsIdentifier(CurrentToken, "end"))
{ {
builder.Add(ParsePropertyDeclaration()); var declaration = ParsePropertyDeclaration();
if (declaration is null)
{
throw new Exception("Property declaration cannot be null.");
}
builder.Add(declaration);
} }
var endKeyword = EatToken(); var endKeyword = EatToken();
return Factory.PropertiesListSyntax(propertiesKeyword, attributes, builder.ToList(), endKeyword); return Factory.PropertiesListSyntax(propertiesKeyword, attributes, builder.ToList(), endKeyword);
} }
private EnumerationItemValueSyntaxNode ParseEnumerationValue() private EnumerationItemValueSyntaxNode? ParseEnumerationValue()
{ {
if (CurrentToken.Kind == TokenKind.OpenParenthesisToken) if (CurrentToken.Kind == TokenKind.OpenParenthesisToken)
{ {
@ -920,7 +1001,12 @@ namespace Parser.Internal
while (CurrentToken.Kind == TokenKind.CommaToken) while (CurrentToken.Kind == TokenKind.CommaToken)
{ {
builder.Add(EatToken()); builder.Add(EatToken());
builder.Add(ParseExpression()); var nextExpression = ParseExpression();
if (nextExpression is null)
{
throw new Exception("Enumeration identifier cannot be empty.");
}
builder.Add(nextExpression);
} }
var closingBracket = EatToken(TokenKind.CloseParenthesisToken); var closingBracket = EatToken(TokenKind.CloseParenthesisToken);
return Factory.EnumerationItemValueSyntax(openingBracket, builder.ToList(), closingBracket); return Factory.EnumerationItemValueSyntax(openingBracket, builder.ToList(), closingBracket);
@ -940,7 +1026,7 @@ namespace Parser.Internal
{ {
var enumerationKeyword = EatToken(); var enumerationKeyword = EatToken();
var builder = new SyntaxListBuilder<EnumerationItemSyntaxNode>(); var builder = new SyntaxListBuilder<EnumerationItemSyntaxNode>();
AttributeListSyntaxNode attributes = null; AttributeListSyntaxNode? attributes = null;
if (CurrentToken.Kind == TokenKind.OpenParenthesisToken) if (CurrentToken.Kind == TokenKind.OpenParenthesisToken)
{ {
attributes = ParseAttributesList(); attributes = ParseAttributesList();
@ -962,7 +1048,7 @@ namespace Parser.Internal
private SyntaxNode ParseEvents() private SyntaxNode ParseEvents()
{ {
var eventsKeyword = EatToken(); var eventsKeyword = EatToken();
AttributeListSyntaxNode attributes = null; AttributeListSyntaxNode? attributes = null;
if (CurrentToken.Kind == TokenKind.OpenParenthesisToken) if (CurrentToken.Kind == TokenKind.OpenParenthesisToken)
{ {
attributes = ParseAttributesList(); attributes = ParseAttributesList();
@ -971,7 +1057,12 @@ namespace Parser.Internal
var builder = new SyntaxListBuilder(); var builder = new SyntaxListBuilder();
while (!IsIdentifier(CurrentToken, "end")) while (!IsIdentifier(CurrentToken, "end"))
{ {
builder.Add(ParseEventDeclaration()); var eventDeclaration = ParseEventDeclaration();
if (eventDeclaration is null)
{
throw new Exception("Event declaration cannot be empty.");
}
builder.Add(eventDeclaration);
} }
var endKeyword = EatToken(); var endKeyword = EatToken();
@ -1001,13 +1092,13 @@ namespace Parser.Internal
private StatementSyntaxNode ParseClassDeclaration() private StatementSyntaxNode ParseClassDeclaration()
{ {
var classdefKeyword = EatToken(); var classdefKeyword = EatToken();
AttributeListSyntaxNode attributes = null; AttributeListSyntaxNode? attributes = null;
if (CurrentToken.Kind == TokenKind.OpenParenthesisToken) if (CurrentToken.Kind == TokenKind.OpenParenthesisToken)
{ {
attributes = ParseAttributesList(); attributes = ParseAttributesList();
} }
var className = Factory.IdentifierNameSyntax(EatToken(TokenKind.IdentifierToken)); var className = Factory.IdentifierNameSyntax(EatToken(TokenKind.IdentifierToken));
BaseClassListSyntaxNode baseClassList = null; BaseClassListSyntaxNode? baseClassList = null;
if (CurrentToken.Kind == TokenKind.LessToken) if (CurrentToken.Kind == TokenKind.LessToken)
{ {
baseClassList = ParseBaseClassList(); baseClassList = ParseBaseClassList();
@ -1052,7 +1143,7 @@ namespace Parser.Internal
endKeyword); endKeyword);
} }
private StatementSyntaxNode ParseStatement() private StatementSyntaxNode? ParseStatement()
{ {
if (CurrentToken.Kind == TokenKind.IdentifierToken) if (CurrentToken.Kind == TokenKind.IdentifierToken)
{ {
@ -1120,5 +1211,11 @@ namespace Parser.Internal
var endOfFileToken = EatToken(); var endOfFileToken = EatToken();
return Factory.FileSyntax(statementList, endOfFileToken); return Factory.FileSyntax(statementList, endOfFileToken);
} }
public RootSyntaxNode ParseRoot()
{
var file = ParseFile();
return Factory.RootSyntax(file);
}
} }
} }

View File

@ -13,12 +13,12 @@ namespace Parser.Internal
public FunctionDeclarationSyntaxNode FunctionDeclarationSyntax( public FunctionDeclarationSyntaxNode FunctionDeclarationSyntax(
SyntaxToken functionKeyword, SyntaxToken functionKeyword,
FunctionOutputDescriptionSyntaxNode outputDescription, FunctionOutputDescriptionSyntaxNode? outputDescription,
SyntaxToken name, SyntaxToken name,
FunctionInputDescriptionSyntaxNode inputDescription, FunctionInputDescriptionSyntaxNode? inputDescription,
SyntaxList<SyntaxToken> commas, SyntaxList<SyntaxToken> commas,
SyntaxList body, SyntaxList body,
SyntaxToken endKeyword) EndKeywordSyntaxNode? endKeyword)
{ {
return new FunctionDeclarationSyntaxNode( return new FunctionDeclarationSyntaxNode(
functionKeyword, functionKeyword,
@ -121,7 +121,7 @@ namespace Parser.Internal
SyntaxList<SyntaxToken> optionalCommas, SyntaxList<SyntaxToken> optionalCommas,
SyntaxList body, SyntaxList body,
SyntaxList<ElseifClause> elseifClauses, SyntaxList<ElseifClause> elseifClauses,
ElseClause elseClause, ElseClause? elseClause,
SyntaxToken endKeyword) SyntaxToken endKeyword)
{ {
return new IfStatementSyntaxNode( return new IfStatementSyntaxNode(
@ -172,7 +172,7 @@ namespace Parser.Internal
public TryCatchStatementSyntaxNode TryCatchStatementSyntax( public TryCatchStatementSyntaxNode TryCatchStatementSyntax(
SyntaxToken tryKeyword, SyntaxToken tryKeyword,
SyntaxList tryBody, SyntaxList tryBody,
CatchClauseSyntaxNode catchClause, CatchClauseSyntaxNode? catchClause,
SyntaxToken endKeyword) SyntaxToken endKeyword)
{ {
return new TryCatchStatementSyntaxNode( return new TryCatchStatementSyntaxNode(
@ -404,7 +404,7 @@ namespace Parser.Internal
public AttributeSyntaxNode AttributeSyntax( public AttributeSyntaxNode AttributeSyntax(
IdentifierNameSyntaxNode name, IdentifierNameSyntaxNode name,
AttributeAssignmentSyntaxNode assignment) AttributeAssignmentSyntaxNode? assignment)
{ {
return new AttributeSyntaxNode( return new AttributeSyntaxNode(
name, name,
@ -424,12 +424,12 @@ namespace Parser.Internal
public MethodDefinitionSyntaxNode MethodDefinitionSyntax( public MethodDefinitionSyntaxNode MethodDefinitionSyntax(
SyntaxToken functionKeyword, SyntaxToken functionKeyword,
FunctionOutputDescriptionSyntaxNode outputDescription, FunctionOutputDescriptionSyntaxNode? outputDescription,
CompoundNameSyntaxNode name, CompoundNameSyntaxNode name,
FunctionInputDescriptionSyntaxNode inputDescription, FunctionInputDescriptionSyntaxNode? inputDescription,
SyntaxList<SyntaxToken> commas, SyntaxList<SyntaxToken> commas,
SyntaxList body, SyntaxList body,
SyntaxToken endKeyword) EndKeywordSyntaxNode? endKeyword)
{ {
return new MethodDefinitionSyntaxNode( return new MethodDefinitionSyntaxNode(
functionKeyword, functionKeyword,
@ -442,9 +442,9 @@ namespace Parser.Internal
} }
public AbstractMethodDeclarationSyntaxNode AbstractMethodDeclarationSyntax( public AbstractMethodDeclarationSyntaxNode AbstractMethodDeclarationSyntax(
FunctionOutputDescriptionSyntaxNode outputDescription, FunctionOutputDescriptionSyntaxNode? outputDescription,
CompoundNameSyntaxNode name, CompoundNameSyntaxNode name,
FunctionInputDescriptionSyntaxNode inputDescription) FunctionInputDescriptionSyntaxNode? inputDescription)
{ {
return new AbstractMethodDeclarationSyntaxNode( return new AbstractMethodDeclarationSyntaxNode(
outputDescription, outputDescription,
@ -454,7 +454,7 @@ namespace Parser.Internal
public MethodsListSyntaxNode MethodsListSyntax( public MethodsListSyntaxNode MethodsListSyntax(
SyntaxToken methodsKeyword, SyntaxToken methodsKeyword,
AttributeListSyntaxNode attributes, AttributeListSyntaxNode? attributes,
SyntaxList methods, SyntaxList methods,
SyntaxToken endKeyword) SyntaxToken endKeyword)
{ {
@ -467,7 +467,7 @@ namespace Parser.Internal
public PropertiesListSyntaxNode PropertiesListSyntax( public PropertiesListSyntaxNode PropertiesListSyntax(
SyntaxToken propertiesKeyword, SyntaxToken propertiesKeyword,
AttributeListSyntaxNode attributes, AttributeListSyntaxNode? attributes,
SyntaxList properties, SyntaxList properties,
SyntaxToken endKeyword) SyntaxToken endKeyword)
{ {
@ -489,9 +489,9 @@ namespace Parser.Internal
public ClassDeclarationSyntaxNode ClassDeclarationSyntax( public ClassDeclarationSyntaxNode ClassDeclarationSyntax(
SyntaxToken classdefKeyword, SyntaxToken classdefKeyword,
AttributeListSyntaxNode attributes, AttributeListSyntaxNode? attributes,
IdentifierNameSyntaxNode className, IdentifierNameSyntaxNode className,
BaseClassListSyntaxNode baseClassList, BaseClassListSyntaxNode? baseClassList,
SyntaxList nodes, SyntaxList nodes,
SyntaxToken endKeyword) SyntaxToken endKeyword)
{ {
@ -517,7 +517,7 @@ namespace Parser.Internal
public EnumerationItemSyntaxNode EnumerationItemSyntax( public EnumerationItemSyntaxNode EnumerationItemSyntax(
IdentifierNameSyntaxNode name, IdentifierNameSyntaxNode name,
EnumerationItemValueSyntaxNode values, EnumerationItemValueSyntaxNode? values,
SyntaxList<SyntaxToken> commas) SyntaxList<SyntaxToken> commas)
{ {
return new EnumerationItemSyntaxNode( return new EnumerationItemSyntaxNode(
@ -528,7 +528,7 @@ namespace Parser.Internal
public EnumerationListSyntaxNode EnumerationListSyntax( public EnumerationListSyntaxNode EnumerationListSyntax(
SyntaxToken enumerationKeyword, SyntaxToken enumerationKeyword,
AttributeListSyntaxNode attributes, AttributeListSyntaxNode? attributes,
SyntaxList<EnumerationItemSyntaxNode> items, SyntaxList<EnumerationItemSyntaxNode> items,
SyntaxToken endKeyword) SyntaxToken endKeyword)
{ {
@ -541,7 +541,7 @@ namespace Parser.Internal
public EventsListSyntaxNode EventsListSyntax( public EventsListSyntaxNode EventsListSyntax(
SyntaxToken eventsKeyword, SyntaxToken eventsKeyword,
AttributeListSyntaxNode attributes, AttributeListSyntaxNode? attributes,
SyntaxList events, SyntaxList events,
SyntaxToken endKeyword) SyntaxToken endKeyword)
{ {
@ -551,5 +551,12 @@ namespace Parser.Internal
events, events,
endKeyword); endKeyword);
} }
public EndKeywordSyntaxNode EndKeywordSyntax(
SyntaxToken endKeyword)
{
return new EndKeywordSyntaxNode(
endKeyword);
}
} }
} }

View File

@ -2,5 +2,9 @@
{ {
internal partial class SyntaxFactory internal partial class SyntaxFactory
{ {
public RootSyntaxNode RootSyntax(FileSyntaxNode file)
{
return new RootSyntaxNode(file);
}
} }
} }

View File

@ -155,7 +155,7 @@ namespace Parser.Internal
} }
} }
private static readonly string[] StringFromKind = private static readonly string?[] StringFromKind =
{ {
null, // None = 0, null, // None = 0,
null, // BadToken = 1, null, // BadToken = 1,
@ -210,7 +210,7 @@ namespace Parser.Internal
"?", // UnaryQuestionMark = 60, "?", // UnaryQuestionMark = 60,
}; };
public static string GetText(TokenKind kind) public static string? GetText(TokenKind kind)
{ {
if ((int) kind < (int) TokenKind.File) if ((int) kind < (int) TokenKind.File)
{ {

View File

@ -17,16 +17,23 @@ namespace Parser.Internal
} }
} }
public override GreenNode GetSlot(int i) public GreenNode GetListSlot(int i)
{ {
return _elements[i]; return _elements[i];
} }
public override GreenNode? GetSlot(int i)
{
return GetListSlot(i);
}
public static SyntaxList List(GreenNode[] elements) public static SyntaxList List(GreenNode[] elements)
{ {
return new SyntaxList(elements); return new SyntaxList(elements);
} }
public static SyntaxList EmptyList { get; } = new SyntaxList(new GreenNode[] { });
public override bool IsList => true; public override bool IsList => true;
internal override Parser.SyntaxNode CreateRed(Parser.SyntaxNode parent, int position) internal override Parser.SyntaxNode CreateRed(Parser.SyntaxNode parent, int position)

View File

@ -20,14 +20,14 @@ namespace Parser.Internal
{ {
for (var i = 0; i < list.Slots; i++) for (var i = 0; i < list.Slots; i++)
{ {
var element = list.GetSlot(i); var element = list.GetListSlot(i);
_list.Add(element); _list.Add(element);
} }
} }
public SyntaxList ToList() public SyntaxList ToList()
{ {
return _list.Count == 0 ? null : SyntaxList.List(_list.ToArray()); return _list.Count == 0 ? SyntaxList.EmptyList : SyntaxList.List(_list.ToArray());
} }
} }
} }

View File

@ -18,7 +18,7 @@ namespace Parser.Internal
public SyntaxList<T> ToList() public SyntaxList<T> ToList()
{ {
return _list.Count == 0 ? null : SyntaxList<T>.List(_list.ToArray()); return _list.Count == 0 ? SyntaxList<T>.Empty : SyntaxList<T>.List(_list.ToArray());
} }
} }

View File

@ -14,9 +14,9 @@
} }
} }
public override GreenNode GetSlot(int i) public override GreenNode? GetSlot(int i)
{ {
return (T)_list.GetSlot(i); return (T)_list.GetListSlot(i);
} }
public static SyntaxList<T> List(T[] elements) public static SyntaxList<T> List(T[] elements)
@ -24,6 +24,8 @@
return new SyntaxList<T>(elements); return new SyntaxList<T>(elements);
} }
public static SyntaxList<T> Empty => new SyntaxList<T>(new T[] { });
public override bool IsList => true; public override bool IsList => true;
internal override Parser.SyntaxNode CreateRed(Parser.SyntaxNode parent, int position) internal override Parser.SyntaxNode CreateRed(Parser.SyntaxNode parent, int position)

View File

@ -9,7 +9,6 @@ namespace Parser.Internal
SyntaxList statementList, SyntaxList statementList,
SyntaxToken endOfFile) : base(TokenKind.File) SyntaxToken endOfFile) : base(TokenKind.File)
{ {
Slots = 2; Slots = 2;
this.AdjustWidth(statementList); this.AdjustWidth(statementList);
_statementList = statementList; _statementList = statementList;
@ -22,7 +21,7 @@ namespace Parser.Internal
return new Parser.FileSyntaxNode(parent, this, position); return new Parser.FileSyntaxNode(parent, this, position);
} }
public override GreenNode GetSlot(int i) public override GreenNode? GetSlot(int i)
{ {
switch (i) switch (i)
{ {
@ -36,23 +35,22 @@ namespace Parser.Internal
internal class FunctionDeclarationSyntaxNode : StatementSyntaxNode internal class FunctionDeclarationSyntaxNode : StatementSyntaxNode
{ {
internal readonly SyntaxToken _functionKeyword; internal readonly SyntaxToken _functionKeyword;
internal readonly FunctionOutputDescriptionSyntaxNode _outputDescription; internal readonly FunctionOutputDescriptionSyntaxNode? _outputDescription;
internal readonly SyntaxToken _name; internal readonly SyntaxToken _name;
internal readonly FunctionInputDescriptionSyntaxNode _inputDescription; internal readonly FunctionInputDescriptionSyntaxNode? _inputDescription;
internal readonly SyntaxList<SyntaxToken> _commas; internal readonly SyntaxList<SyntaxToken> _commas;
internal readonly SyntaxList _body; internal readonly SyntaxList _body;
internal readonly SyntaxToken _endKeyword; internal readonly EndKeywordSyntaxNode? _endKeyword;
internal FunctionDeclarationSyntaxNode( internal FunctionDeclarationSyntaxNode(
SyntaxToken functionKeyword, SyntaxToken functionKeyword,
FunctionOutputDescriptionSyntaxNode outputDescription, FunctionOutputDescriptionSyntaxNode? outputDescription,
SyntaxToken name, SyntaxToken name,
FunctionInputDescriptionSyntaxNode inputDescription, FunctionInputDescriptionSyntaxNode? inputDescription,
SyntaxList<SyntaxToken> commas, SyntaxList<SyntaxToken> commas,
SyntaxList body, SyntaxList body,
SyntaxToken endKeyword) : base(TokenKind.FunctionDeclaration) EndKeywordSyntaxNode? endKeyword) : base(TokenKind.FunctionDeclaration)
{ {
Slots = 7; Slots = 7;
this.AdjustWidth(functionKeyword); this.AdjustWidth(functionKeyword);
_functionKeyword = functionKeyword; _functionKeyword = functionKeyword;
@ -75,7 +73,7 @@ namespace Parser.Internal
return new Parser.FunctionDeclarationSyntaxNode(parent, this, position); return new Parser.FunctionDeclarationSyntaxNode(parent, this, position);
} }
public override GreenNode GetSlot(int i) public override GreenNode? GetSlot(int i)
{ {
switch (i) switch (i)
{ {
@ -100,7 +98,6 @@ namespace Parser.Internal
SyntaxList outputList, SyntaxList outputList,
SyntaxToken assignmentSign) : base(TokenKind.FunctionOutputDescription) SyntaxToken assignmentSign) : base(TokenKind.FunctionOutputDescription)
{ {
Slots = 2; Slots = 2;
this.AdjustWidth(outputList); this.AdjustWidth(outputList);
_outputList = outputList; _outputList = outputList;
@ -113,7 +110,7 @@ namespace Parser.Internal
return new Parser.FunctionOutputDescriptionSyntaxNode(parent, this, position); return new Parser.FunctionOutputDescriptionSyntaxNode(parent, this, position);
} }
public override GreenNode GetSlot(int i) public override GreenNode? GetSlot(int i)
{ {
switch (i) switch (i)
{ {
@ -135,7 +132,6 @@ namespace Parser.Internal
SyntaxList parameterList, SyntaxList parameterList,
SyntaxToken closingBracket) : base(TokenKind.FunctionInputDescription) SyntaxToken closingBracket) : base(TokenKind.FunctionInputDescription)
{ {
Slots = 3; Slots = 3;
this.AdjustWidth(openingBracket); this.AdjustWidth(openingBracket);
_openingBracket = openingBracket; _openingBracket = openingBracket;
@ -150,7 +146,7 @@ namespace Parser.Internal
return new Parser.FunctionInputDescriptionSyntaxNode(parent, this, position); return new Parser.FunctionInputDescriptionSyntaxNode(parent, this, position);
} }
public override GreenNode GetSlot(int i) public override GreenNode? GetSlot(int i)
{ {
switch (i) switch (i)
{ {
@ -177,7 +173,6 @@ namespace Parser.Internal
SyntaxList<SwitchCaseSyntaxNode> cases, SyntaxList<SwitchCaseSyntaxNode> cases,
SyntaxToken endKeyword) : base(TokenKind.SwitchStatement) SyntaxToken endKeyword) : base(TokenKind.SwitchStatement)
{ {
Slots = 5; Slots = 5;
this.AdjustWidth(switchKeyword); this.AdjustWidth(switchKeyword);
_switchKeyword = switchKeyword; _switchKeyword = switchKeyword;
@ -196,7 +191,7 @@ namespace Parser.Internal
return new Parser.SwitchStatementSyntaxNode(parent, this, position); return new Parser.SwitchStatementSyntaxNode(parent, this, position);
} }
public override GreenNode GetSlot(int i) public override GreenNode? GetSlot(int i)
{ {
switch (i) switch (i)
{ {
@ -223,7 +218,6 @@ namespace Parser.Internal
SyntaxList<SyntaxToken> optionalCommas, SyntaxList<SyntaxToken> optionalCommas,
SyntaxList body) : base(TokenKind.SwitchCase) SyntaxList body) : base(TokenKind.SwitchCase)
{ {
Slots = 4; Slots = 4;
this.AdjustWidth(caseKeyword); this.AdjustWidth(caseKeyword);
_caseKeyword = caseKeyword; _caseKeyword = caseKeyword;
@ -240,7 +234,7 @@ namespace Parser.Internal
return new Parser.SwitchCaseSyntaxNode(parent, this, position); return new Parser.SwitchCaseSyntaxNode(parent, this, position);
} }
public override GreenNode GetSlot(int i) public override GreenNode? GetSlot(int i)
{ {
switch (i) switch (i)
{ {
@ -268,7 +262,6 @@ namespace Parser.Internal
SyntaxList body, SyntaxList body,
SyntaxToken endKeyword) : base(TokenKind.WhileStatement) SyntaxToken endKeyword) : base(TokenKind.WhileStatement)
{ {
Slots = 5; Slots = 5;
this.AdjustWidth(whileKeyword); this.AdjustWidth(whileKeyword);
_whileKeyword = whileKeyword; _whileKeyword = whileKeyword;
@ -287,7 +280,7 @@ namespace Parser.Internal
return new Parser.WhileStatementSyntaxNode(parent, this, position); return new Parser.WhileStatementSyntaxNode(parent, this, position);
} }
public override GreenNode GetSlot(int i) public override GreenNode? GetSlot(int i)
{ {
switch (i) switch (i)
{ {
@ -314,7 +307,6 @@ namespace Parser.Internal
SyntaxList<SyntaxToken> optionalCommas, SyntaxList<SyntaxToken> optionalCommas,
SyntaxList body) : base(TokenKind.ElseifClause) SyntaxList body) : base(TokenKind.ElseifClause)
{ {
Slots = 4; Slots = 4;
this.AdjustWidth(elseifKeyword); this.AdjustWidth(elseifKeyword);
_elseifKeyword = elseifKeyword; _elseifKeyword = elseifKeyword;
@ -331,7 +323,7 @@ namespace Parser.Internal
return new Parser.ElseifClause(parent, this, position); return new Parser.ElseifClause(parent, this, position);
} }
public override GreenNode GetSlot(int i) public override GreenNode? GetSlot(int i)
{ {
switch (i) switch (i)
{ {
@ -353,7 +345,6 @@ namespace Parser.Internal
SyntaxToken elseKeyword, SyntaxToken elseKeyword,
SyntaxList body) : base(TokenKind.ElseClause) SyntaxList body) : base(TokenKind.ElseClause)
{ {
Slots = 2; Slots = 2;
this.AdjustWidth(elseKeyword); this.AdjustWidth(elseKeyword);
_elseKeyword = elseKeyword; _elseKeyword = elseKeyword;
@ -366,7 +357,7 @@ namespace Parser.Internal
return new Parser.ElseClause(parent, this, position); return new Parser.ElseClause(parent, this, position);
} }
public override GreenNode GetSlot(int i) public override GreenNode? GetSlot(int i)
{ {
switch (i) switch (i)
{ {
@ -384,7 +375,7 @@ namespace Parser.Internal
internal readonly SyntaxList<SyntaxToken> _optionalCommas; internal readonly SyntaxList<SyntaxToken> _optionalCommas;
internal readonly SyntaxList _body; internal readonly SyntaxList _body;
internal readonly SyntaxList<ElseifClause> _elseifClauses; internal readonly SyntaxList<ElseifClause> _elseifClauses;
internal readonly ElseClause _elseClause; internal readonly ElseClause? _elseClause;
internal readonly SyntaxToken _endKeyword; internal readonly SyntaxToken _endKeyword;
internal IfStatementSyntaxNode( internal IfStatementSyntaxNode(
@ -393,10 +384,9 @@ namespace Parser.Internal
SyntaxList<SyntaxToken> optionalCommas, SyntaxList<SyntaxToken> optionalCommas,
SyntaxList body, SyntaxList body,
SyntaxList<ElseifClause> elseifClauses, SyntaxList<ElseifClause> elseifClauses,
ElseClause elseClause, ElseClause? elseClause,
SyntaxToken endKeyword) : base(TokenKind.IfStatement) SyntaxToken endKeyword) : base(TokenKind.IfStatement)
{ {
Slots = 7; Slots = 7;
this.AdjustWidth(ifKeyword); this.AdjustWidth(ifKeyword);
_ifKeyword = ifKeyword; _ifKeyword = ifKeyword;
@ -419,7 +409,7 @@ namespace Parser.Internal
return new Parser.IfStatementSyntaxNode(parent, this, position); return new Parser.IfStatementSyntaxNode(parent, this, position);
} }
public override GreenNode GetSlot(int i) public override GreenNode? GetSlot(int i)
{ {
switch (i) switch (i)
{ {
@ -450,7 +440,6 @@ namespace Parser.Internal
SyntaxList body, SyntaxList body,
SyntaxToken endKeyword) : base(TokenKind.ForStatement) SyntaxToken endKeyword) : base(TokenKind.ForStatement)
{ {
Slots = 5; Slots = 5;
this.AdjustWidth(forKeyword); this.AdjustWidth(forKeyword);
_forKeyword = forKeyword; _forKeyword = forKeyword;
@ -469,7 +458,7 @@ namespace Parser.Internal
return new Parser.ForStatementSyntaxNode(parent, this, position); return new Parser.ForStatementSyntaxNode(parent, this, position);
} }
public override GreenNode GetSlot(int i) public override GreenNode? GetSlot(int i)
{ {
switch (i) switch (i)
{ {
@ -494,7 +483,6 @@ namespace Parser.Internal
SyntaxToken assignmentSign, SyntaxToken assignmentSign,
ExpressionSyntaxNode rhs) : base(TokenKind.AssignmentExpression) ExpressionSyntaxNode rhs) : base(TokenKind.AssignmentExpression)
{ {
Slots = 3; Slots = 3;
this.AdjustWidth(lhs); this.AdjustWidth(lhs);
_lhs = lhs; _lhs = lhs;
@ -509,7 +497,7 @@ namespace Parser.Internal
return new Parser.AssignmentExpressionSyntaxNode(parent, this, position); return new Parser.AssignmentExpressionSyntaxNode(parent, this, position);
} }
public override GreenNode GetSlot(int i) public override GreenNode? GetSlot(int i)
{ {
switch (i) switch (i)
{ {
@ -530,7 +518,6 @@ namespace Parser.Internal
SyntaxToken catchKeyword, SyntaxToken catchKeyword,
SyntaxList catchBody) : base(TokenKind.CatchClause) SyntaxList catchBody) : base(TokenKind.CatchClause)
{ {
Slots = 2; Slots = 2;
this.AdjustWidth(catchKeyword); this.AdjustWidth(catchKeyword);
_catchKeyword = catchKeyword; _catchKeyword = catchKeyword;
@ -543,7 +530,7 @@ namespace Parser.Internal
return new Parser.CatchClauseSyntaxNode(parent, this, position); return new Parser.CatchClauseSyntaxNode(parent, this, position);
} }
public override GreenNode GetSlot(int i) public override GreenNode? GetSlot(int i)
{ {
switch (i) switch (i)
{ {
@ -558,16 +545,15 @@ namespace Parser.Internal
{ {
internal readonly SyntaxToken _tryKeyword; internal readonly SyntaxToken _tryKeyword;
internal readonly SyntaxList _tryBody; internal readonly SyntaxList _tryBody;
internal readonly CatchClauseSyntaxNode _catchClause; internal readonly CatchClauseSyntaxNode? _catchClause;
internal readonly SyntaxToken _endKeyword; internal readonly SyntaxToken _endKeyword;
internal TryCatchStatementSyntaxNode( internal TryCatchStatementSyntaxNode(
SyntaxToken tryKeyword, SyntaxToken tryKeyword,
SyntaxList tryBody, SyntaxList tryBody,
CatchClauseSyntaxNode catchClause, CatchClauseSyntaxNode? catchClause,
SyntaxToken endKeyword) : base(TokenKind.TryCatchStatement) SyntaxToken endKeyword) : base(TokenKind.TryCatchStatement)
{ {
Slots = 4; Slots = 4;
this.AdjustWidth(tryKeyword); this.AdjustWidth(tryKeyword);
_tryKeyword = tryKeyword; _tryKeyword = tryKeyword;
@ -584,7 +570,7 @@ namespace Parser.Internal
return new Parser.TryCatchStatementSyntaxNode(parent, this, position); return new Parser.TryCatchStatementSyntaxNode(parent, this, position);
} }
public override GreenNode GetSlot(int i) public override GreenNode? GetSlot(int i)
{ {
switch (i) switch (i)
{ {
@ -604,7 +590,6 @@ namespace Parser.Internal
internal ExpressionStatementSyntaxNode( internal ExpressionStatementSyntaxNode(
ExpressionSyntaxNode expression) : base(TokenKind.ExpressionStatement) ExpressionSyntaxNode expression) : base(TokenKind.ExpressionStatement)
{ {
Slots = 1; Slots = 1;
this.AdjustWidth(expression); this.AdjustWidth(expression);
_expression = expression; _expression = expression;
@ -615,7 +600,7 @@ namespace Parser.Internal
return new Parser.ExpressionStatementSyntaxNode(parent, this, position); return new Parser.ExpressionStatementSyntaxNode(parent, this, position);
} }
public override GreenNode GetSlot(int i) public override GreenNode? GetSlot(int i)
{ {
switch (i) switch (i)
{ {
@ -632,7 +617,6 @@ namespace Parser.Internal
internal EmptyStatementSyntaxNode( internal EmptyStatementSyntaxNode(
SyntaxToken semicolon) : base(TokenKind.EmptyStatement) SyntaxToken semicolon) : base(TokenKind.EmptyStatement)
{ {
Slots = 1; Slots = 1;
this.AdjustWidth(semicolon); this.AdjustWidth(semicolon);
_semicolon = semicolon; _semicolon = semicolon;
@ -643,7 +627,7 @@ namespace Parser.Internal
return new Parser.EmptyStatementSyntaxNode(parent, this, position); return new Parser.EmptyStatementSyntaxNode(parent, this, position);
} }
public override GreenNode GetSlot(int i) public override GreenNode? GetSlot(int i)
{ {
switch (i) switch (i)
{ {
@ -658,7 +642,6 @@ namespace Parser.Internal
internal EmptyExpressionSyntaxNode() : base(TokenKind.EmptyExpression) internal EmptyExpressionSyntaxNode() : base(TokenKind.EmptyExpression)
{ {
Slots = 0; Slots = 0;
} }
@ -667,7 +650,7 @@ namespace Parser.Internal
return new Parser.EmptyExpressionSyntaxNode(parent, this, position); return new Parser.EmptyExpressionSyntaxNode(parent, this, position);
} }
public override GreenNode GetSlot(int i) public override GreenNode? GetSlot(int i)
{ {
switch (i) switch (i)
{ {
@ -685,7 +668,6 @@ namespace Parser.Internal
SyntaxToken operation, SyntaxToken operation,
ExpressionSyntaxNode operand) : base(TokenKind.UnaryPrefixOperationExpression) ExpressionSyntaxNode operand) : base(TokenKind.UnaryPrefixOperationExpression)
{ {
Slots = 2; Slots = 2;
this.AdjustWidth(operation); this.AdjustWidth(operation);
_operation = operation; _operation = operation;
@ -698,7 +680,7 @@ namespace Parser.Internal
return new Parser.UnaryPrefixOperationExpressionSyntaxNode(parent, this, position); return new Parser.UnaryPrefixOperationExpressionSyntaxNode(parent, this, position);
} }
public override GreenNode GetSlot(int i) public override GreenNode? GetSlot(int i)
{ {
switch (i) switch (i)
{ {
@ -716,7 +698,6 @@ namespace Parser.Internal
internal CompoundNameSyntaxNode( internal CompoundNameSyntaxNode(
SyntaxList nodes) : base(TokenKind.CompoundName) SyntaxList nodes) : base(TokenKind.CompoundName)
{ {
Slots = 1; Slots = 1;
this.AdjustWidth(nodes); this.AdjustWidth(nodes);
_nodes = nodes; _nodes = nodes;
@ -727,7 +708,7 @@ namespace Parser.Internal
return new Parser.CompoundNameSyntaxNode(parent, this, position); return new Parser.CompoundNameSyntaxNode(parent, this, position);
} }
public override GreenNode GetSlot(int i) public override GreenNode? GetSlot(int i)
{ {
switch (i) switch (i)
{ {
@ -746,7 +727,6 @@ namespace Parser.Internal
SyntaxToken atSign, SyntaxToken atSign,
CompoundNameSyntaxNode functionName) : base(TokenKind.NamedFunctionHandle) CompoundNameSyntaxNode functionName) : base(TokenKind.NamedFunctionHandle)
{ {
Slots = 2; Slots = 2;
this.AdjustWidth(atSign); this.AdjustWidth(atSign);
_atSign = atSign; _atSign = atSign;
@ -759,7 +739,7 @@ namespace Parser.Internal
return new Parser.NamedFunctionHandleSyntaxNode(parent, this, position); return new Parser.NamedFunctionHandleSyntaxNode(parent, this, position);
} }
public override GreenNode GetSlot(int i) public override GreenNode? GetSlot(int i)
{ {
switch (i) switch (i)
{ {
@ -781,7 +761,6 @@ namespace Parser.Internal
FunctionInputDescriptionSyntaxNode input, FunctionInputDescriptionSyntaxNode input,
ExpressionSyntaxNode body) : base(TokenKind.Lambda) ExpressionSyntaxNode body) : base(TokenKind.Lambda)
{ {
Slots = 3; Slots = 3;
this.AdjustWidth(atSign); this.AdjustWidth(atSign);
_atSign = atSign; _atSign = atSign;
@ -796,7 +775,7 @@ namespace Parser.Internal
return new Parser.LambdaSyntaxNode(parent, this, position); return new Parser.LambdaSyntaxNode(parent, this, position);
} }
public override GreenNode GetSlot(int i) public override GreenNode? GetSlot(int i)
{ {
switch (i) switch (i)
{ {
@ -819,7 +798,6 @@ namespace Parser.Internal
SyntaxToken operation, SyntaxToken operation,
ExpressionSyntaxNode rhs) : base(TokenKind.BinaryOperation) ExpressionSyntaxNode rhs) : base(TokenKind.BinaryOperation)
{ {
Slots = 3; Slots = 3;
this.AdjustWidth(lhs); this.AdjustWidth(lhs);
_lhs = lhs; _lhs = lhs;
@ -834,7 +812,7 @@ namespace Parser.Internal
return new Parser.BinaryOperationExpressionSyntaxNode(parent, this, position); return new Parser.BinaryOperationExpressionSyntaxNode(parent, this, position);
} }
public override GreenNode GetSlot(int i) public override GreenNode? GetSlot(int i)
{ {
switch (i) switch (i)
{ {
@ -853,7 +831,6 @@ namespace Parser.Internal
internal IdentifierNameSyntaxNode( internal IdentifierNameSyntaxNode(
SyntaxToken name) : base(TokenKind.IdentifierName) SyntaxToken name) : base(TokenKind.IdentifierName)
{ {
Slots = 1; Slots = 1;
this.AdjustWidth(name); this.AdjustWidth(name);
_name = name; _name = name;
@ -864,7 +841,7 @@ namespace Parser.Internal
return new Parser.IdentifierNameSyntaxNode(parent, this, position); return new Parser.IdentifierNameSyntaxNode(parent, this, position);
} }
public override GreenNode GetSlot(int i) public override GreenNode? GetSlot(int i)
{ {
switch (i) switch (i)
{ {
@ -881,7 +858,6 @@ namespace Parser.Internal
internal NumberLiteralSyntaxNode( internal NumberLiteralSyntaxNode(
SyntaxToken number) : base(TokenKind.NumberLiteralExpression) SyntaxToken number) : base(TokenKind.NumberLiteralExpression)
{ {
Slots = 1; Slots = 1;
this.AdjustWidth(number); this.AdjustWidth(number);
_number = number; _number = number;
@ -892,7 +868,7 @@ namespace Parser.Internal
return new Parser.NumberLiteralSyntaxNode(parent, this, position); return new Parser.NumberLiteralSyntaxNode(parent, this, position);
} }
public override GreenNode GetSlot(int i) public override GreenNode? GetSlot(int i)
{ {
switch (i) switch (i)
{ {
@ -909,7 +885,6 @@ namespace Parser.Internal
internal StringLiteralSyntaxNode( internal StringLiteralSyntaxNode(
SyntaxToken stringToken) : base(TokenKind.StringLiteralExpression) SyntaxToken stringToken) : base(TokenKind.StringLiteralExpression)
{ {
Slots = 1; Slots = 1;
this.AdjustWidth(stringToken); this.AdjustWidth(stringToken);
_stringToken = stringToken; _stringToken = stringToken;
@ -920,7 +895,7 @@ namespace Parser.Internal
return new Parser.StringLiteralSyntaxNode(parent, this, position); return new Parser.StringLiteralSyntaxNode(parent, this, position);
} }
public override GreenNode GetSlot(int i) public override GreenNode? GetSlot(int i)
{ {
switch (i) switch (i)
{ {
@ -937,7 +912,6 @@ namespace Parser.Internal
internal DoubleQuotedStringLiteralSyntaxNode( internal DoubleQuotedStringLiteralSyntaxNode(
SyntaxToken stringToken) : base(TokenKind.DoubleQuotedStringLiteralExpression) SyntaxToken stringToken) : base(TokenKind.DoubleQuotedStringLiteralExpression)
{ {
Slots = 1; Slots = 1;
this.AdjustWidth(stringToken); this.AdjustWidth(stringToken);
_stringToken = stringToken; _stringToken = stringToken;
@ -948,7 +922,7 @@ namespace Parser.Internal
return new Parser.DoubleQuotedStringLiteralSyntaxNode(parent, this, position); return new Parser.DoubleQuotedStringLiteralSyntaxNode(parent, this, position);
} }
public override GreenNode GetSlot(int i) public override GreenNode? GetSlot(int i)
{ {
switch (i) switch (i)
{ {
@ -965,7 +939,6 @@ namespace Parser.Internal
internal UnquotedStringLiteralSyntaxNode( internal UnquotedStringLiteralSyntaxNode(
SyntaxToken stringToken) : base(TokenKind.UnquotedStringLiteralExpression) SyntaxToken stringToken) : base(TokenKind.UnquotedStringLiteralExpression)
{ {
Slots = 1; Slots = 1;
this.AdjustWidth(stringToken); this.AdjustWidth(stringToken);
_stringToken = stringToken; _stringToken = stringToken;
@ -976,7 +949,7 @@ namespace Parser.Internal
return new Parser.UnquotedStringLiteralSyntaxNode(parent, this, position); return new Parser.UnquotedStringLiteralSyntaxNode(parent, this, position);
} }
public override GreenNode GetSlot(int i) public override GreenNode? GetSlot(int i)
{ {
switch (i) switch (i)
{ {
@ -997,7 +970,6 @@ namespace Parser.Internal
SyntaxList nodes, SyntaxList nodes,
SyntaxToken closingSquareBracket) : base(TokenKind.ArrayLiteralExpression) SyntaxToken closingSquareBracket) : base(TokenKind.ArrayLiteralExpression)
{ {
Slots = 3; Slots = 3;
this.AdjustWidth(openingSquareBracket); this.AdjustWidth(openingSquareBracket);
_openingSquareBracket = openingSquareBracket; _openingSquareBracket = openingSquareBracket;
@ -1012,7 +984,7 @@ namespace Parser.Internal
return new Parser.ArrayLiteralExpressionSyntaxNode(parent, this, position); return new Parser.ArrayLiteralExpressionSyntaxNode(parent, this, position);
} }
public override GreenNode GetSlot(int i) public override GreenNode? GetSlot(int i)
{ {
switch (i) switch (i)
{ {
@ -1035,7 +1007,6 @@ namespace Parser.Internal
SyntaxList nodes, SyntaxList nodes,
SyntaxToken closingBrace) : base(TokenKind.CellArrayLiteralExpression) SyntaxToken closingBrace) : base(TokenKind.CellArrayLiteralExpression)
{ {
Slots = 3; Slots = 3;
this.AdjustWidth(openingBrace); this.AdjustWidth(openingBrace);
_openingBrace = openingBrace; _openingBrace = openingBrace;
@ -1050,7 +1021,7 @@ namespace Parser.Internal
return new Parser.CellArrayLiteralExpressionSyntaxNode(parent, this, position); return new Parser.CellArrayLiteralExpressionSyntaxNode(parent, this, position);
} }
public override GreenNode GetSlot(int i) public override GreenNode? GetSlot(int i)
{ {
switch (i) switch (i)
{ {
@ -1073,7 +1044,6 @@ namespace Parser.Internal
ExpressionSyntaxNode expression, ExpressionSyntaxNode expression,
SyntaxToken closingBracket) : base(TokenKind.ParenthesizedExpression) SyntaxToken closingBracket) : base(TokenKind.ParenthesizedExpression)
{ {
Slots = 3; Slots = 3;
this.AdjustWidth(openingBracket); this.AdjustWidth(openingBracket);
_openingBracket = openingBracket; _openingBracket = openingBracket;
@ -1088,7 +1058,7 @@ namespace Parser.Internal
return new Parser.ParenthesizedExpressionSyntaxNode(parent, this, position); return new Parser.ParenthesizedExpressionSyntaxNode(parent, this, position);
} }
public override GreenNode GetSlot(int i) public override GreenNode? GetSlot(int i)
{ {
switch (i) switch (i)
{ {
@ -1113,7 +1083,6 @@ namespace Parser.Internal
SyntaxList nodes, SyntaxList nodes,
SyntaxToken closingBrace) : base(TokenKind.CellArrayElementAccess) SyntaxToken closingBrace) : base(TokenKind.CellArrayElementAccess)
{ {
Slots = 4; Slots = 4;
this.AdjustWidth(expression); this.AdjustWidth(expression);
_expression = expression; _expression = expression;
@ -1130,7 +1099,7 @@ namespace Parser.Internal
return new Parser.CellArrayElementAccessExpressionSyntaxNode(parent, this, position); return new Parser.CellArrayElementAccessExpressionSyntaxNode(parent, this, position);
} }
public override GreenNode GetSlot(int i) public override GreenNode? GetSlot(int i)
{ {
switch (i) switch (i)
{ {
@ -1156,7 +1125,6 @@ namespace Parser.Internal
SyntaxList nodes, SyntaxList nodes,
SyntaxToken closingBracket) : base(TokenKind.FunctionCall) SyntaxToken closingBracket) : base(TokenKind.FunctionCall)
{ {
Slots = 4; Slots = 4;
this.AdjustWidth(functionName); this.AdjustWidth(functionName);
_functionName = functionName; _functionName = functionName;
@ -1173,7 +1141,7 @@ namespace Parser.Internal
return new Parser.FunctionCallExpressionSyntaxNode(parent, this, position); return new Parser.FunctionCallExpressionSyntaxNode(parent, this, position);
} }
public override GreenNode GetSlot(int i) public override GreenNode? GetSlot(int i)
{ {
switch (i) switch (i)
{ {
@ -1197,7 +1165,6 @@ namespace Parser.Internal
SyntaxToken dot, SyntaxToken dot,
SyntaxNode rightOperand) : base(TokenKind.MemberAccess) SyntaxNode rightOperand) : base(TokenKind.MemberAccess)
{ {
Slots = 3; Slots = 3;
this.AdjustWidth(leftOperand); this.AdjustWidth(leftOperand);
_leftOperand = leftOperand; _leftOperand = leftOperand;
@ -1212,7 +1179,7 @@ namespace Parser.Internal
return new Parser.MemberAccessSyntaxNode(parent, this, position); return new Parser.MemberAccessSyntaxNode(parent, this, position);
} }
public override GreenNode GetSlot(int i) public override GreenNode? GetSlot(int i)
{ {
switch (i) switch (i)
{ {
@ -1233,7 +1200,6 @@ namespace Parser.Internal
ExpressionSyntaxNode operand, ExpressionSyntaxNode operand,
SyntaxToken operation) : base(TokenKind.UnaryPostfixOperationExpression) SyntaxToken operation) : base(TokenKind.UnaryPostfixOperationExpression)
{ {
Slots = 2; Slots = 2;
this.AdjustWidth(operand); this.AdjustWidth(operand);
_operand = operand; _operand = operand;
@ -1246,7 +1212,7 @@ namespace Parser.Internal
return new Parser.UnaryPostixOperationExpressionSyntaxNode(parent, this, position); return new Parser.UnaryPostixOperationExpressionSyntaxNode(parent, this, position);
} }
public override GreenNode GetSlot(int i) public override GreenNode? GetSlot(int i)
{ {
switch (i) switch (i)
{ {
@ -1268,7 +1234,6 @@ namespace Parser.Internal
ExpressionSyntaxNode expression, ExpressionSyntaxNode expression,
SyntaxToken closingBracket) : base(TokenKind.IndirectMemberAccess) SyntaxToken closingBracket) : base(TokenKind.IndirectMemberAccess)
{ {
Slots = 3; Slots = 3;
this.AdjustWidth(openingBracket); this.AdjustWidth(openingBracket);
_openingBracket = openingBracket; _openingBracket = openingBracket;
@ -1283,7 +1248,7 @@ namespace Parser.Internal
return new Parser.IndirectMemberAccessSyntaxNode(parent, this, position); return new Parser.IndirectMemberAccessSyntaxNode(parent, this, position);
} }
public override GreenNode GetSlot(int i) public override GreenNode? GetSlot(int i)
{ {
switch (i) switch (i)
{ {
@ -1304,7 +1269,6 @@ namespace Parser.Internal
IdentifierNameSyntaxNode commandName, IdentifierNameSyntaxNode commandName,
SyntaxList<UnquotedStringLiteralSyntaxNode> arguments) : base(TokenKind.Command) SyntaxList<UnquotedStringLiteralSyntaxNode> arguments) : base(TokenKind.Command)
{ {
Slots = 2; Slots = 2;
this.AdjustWidth(commandName); this.AdjustWidth(commandName);
_commandName = commandName; _commandName = commandName;
@ -1317,7 +1281,7 @@ namespace Parser.Internal
return new Parser.CommandExpressionSyntaxNode(parent, this, position); return new Parser.CommandExpressionSyntaxNode(parent, this, position);
} }
public override GreenNode GetSlot(int i) public override GreenNode? GetSlot(int i)
{ {
switch (i) switch (i)
{ {
@ -1339,7 +1303,6 @@ namespace Parser.Internal
SyntaxToken atSign, SyntaxToken atSign,
ExpressionSyntaxNode baseClassNameAndArguments) : base(TokenKind.ClassInvokation) ExpressionSyntaxNode baseClassNameAndArguments) : base(TokenKind.ClassInvokation)
{ {
Slots = 3; Slots = 3;
this.AdjustWidth(methodName); this.AdjustWidth(methodName);
_methodName = methodName; _methodName = methodName;
@ -1354,7 +1317,7 @@ namespace Parser.Internal
return new Parser.BaseClassInvokationSyntaxNode(parent, this, position); return new Parser.BaseClassInvokationSyntaxNode(parent, this, position);
} }
public override GreenNode GetSlot(int i) public override GreenNode? GetSlot(int i)
{ {
switch (i) switch (i)
{ {
@ -1375,7 +1338,6 @@ namespace Parser.Internal
SyntaxToken assignmentSign, SyntaxToken assignmentSign,
ExpressionSyntaxNode value) : base(TokenKind.AttributeAssignment) ExpressionSyntaxNode value) : base(TokenKind.AttributeAssignment)
{ {
Slots = 2; Slots = 2;
this.AdjustWidth(assignmentSign); this.AdjustWidth(assignmentSign);
_assignmentSign = assignmentSign; _assignmentSign = assignmentSign;
@ -1388,7 +1350,7 @@ namespace Parser.Internal
return new Parser.AttributeAssignmentSyntaxNode(parent, this, position); return new Parser.AttributeAssignmentSyntaxNode(parent, this, position);
} }
public override GreenNode GetSlot(int i) public override GreenNode? GetSlot(int i)
{ {
switch (i) switch (i)
{ {
@ -1402,13 +1364,12 @@ namespace Parser.Internal
internal class AttributeSyntaxNode : SyntaxNode internal class AttributeSyntaxNode : SyntaxNode
{ {
internal readonly IdentifierNameSyntaxNode _name; internal readonly IdentifierNameSyntaxNode _name;
internal readonly AttributeAssignmentSyntaxNode _assignment; internal readonly AttributeAssignmentSyntaxNode? _assignment;
internal AttributeSyntaxNode( internal AttributeSyntaxNode(
IdentifierNameSyntaxNode name, IdentifierNameSyntaxNode name,
AttributeAssignmentSyntaxNode assignment) : base(TokenKind.Attribute) AttributeAssignmentSyntaxNode? assignment) : base(TokenKind.Attribute)
{ {
Slots = 2; Slots = 2;
this.AdjustWidth(name); this.AdjustWidth(name);
_name = name; _name = name;
@ -1421,7 +1382,7 @@ namespace Parser.Internal
return new Parser.AttributeSyntaxNode(parent, this, position); return new Parser.AttributeSyntaxNode(parent, this, position);
} }
public override GreenNode GetSlot(int i) public override GreenNode? GetSlot(int i)
{ {
switch (i) switch (i)
{ {
@ -1443,7 +1404,6 @@ namespace Parser.Internal
SyntaxList nodes, SyntaxList nodes,
SyntaxToken closingBracket) : base(TokenKind.AttributeList) SyntaxToken closingBracket) : base(TokenKind.AttributeList)
{ {
Slots = 3; Slots = 3;
this.AdjustWidth(openingBracket); this.AdjustWidth(openingBracket);
_openingBracket = openingBracket; _openingBracket = openingBracket;
@ -1458,7 +1418,7 @@ namespace Parser.Internal
return new Parser.AttributeListSyntaxNode(parent, this, position); return new Parser.AttributeListSyntaxNode(parent, this, position);
} }
public override GreenNode GetSlot(int i) public override GreenNode? GetSlot(int i)
{ {
switch (i) switch (i)
{ {
@ -1473,23 +1433,22 @@ namespace Parser.Internal
internal class MethodDefinitionSyntaxNode : MethodDeclarationSyntaxNode internal class MethodDefinitionSyntaxNode : MethodDeclarationSyntaxNode
{ {
internal readonly SyntaxToken _functionKeyword; internal readonly SyntaxToken _functionKeyword;
internal readonly FunctionOutputDescriptionSyntaxNode _outputDescription; internal readonly FunctionOutputDescriptionSyntaxNode? _outputDescription;
internal readonly CompoundNameSyntaxNode _name; internal readonly CompoundNameSyntaxNode _name;
internal readonly FunctionInputDescriptionSyntaxNode _inputDescription; internal readonly FunctionInputDescriptionSyntaxNode? _inputDescription;
internal readonly SyntaxList<SyntaxToken> _commas; internal readonly SyntaxList<SyntaxToken> _commas;
internal readonly SyntaxList _body; internal readonly SyntaxList _body;
internal readonly SyntaxToken _endKeyword; internal readonly EndKeywordSyntaxNode? _endKeyword;
internal MethodDefinitionSyntaxNode( internal MethodDefinitionSyntaxNode(
SyntaxToken functionKeyword, SyntaxToken functionKeyword,
FunctionOutputDescriptionSyntaxNode outputDescription, FunctionOutputDescriptionSyntaxNode? outputDescription,
CompoundNameSyntaxNode name, CompoundNameSyntaxNode name,
FunctionInputDescriptionSyntaxNode inputDescription, FunctionInputDescriptionSyntaxNode? inputDescription,
SyntaxList<SyntaxToken> commas, SyntaxList<SyntaxToken> commas,
SyntaxList body, SyntaxList body,
SyntaxToken endKeyword) : base(TokenKind.MethodDefinition) EndKeywordSyntaxNode? endKeyword) : base(TokenKind.MethodDefinition)
{ {
Slots = 7; Slots = 7;
this.AdjustWidth(functionKeyword); this.AdjustWidth(functionKeyword);
_functionKeyword = functionKeyword; _functionKeyword = functionKeyword;
@ -1512,7 +1471,7 @@ namespace Parser.Internal
return new Parser.MethodDefinitionSyntaxNode(parent, this, position); return new Parser.MethodDefinitionSyntaxNode(parent, this, position);
} }
public override GreenNode GetSlot(int i) public override GreenNode? GetSlot(int i)
{ {
switch (i) switch (i)
{ {
@ -1530,16 +1489,15 @@ namespace Parser.Internal
internal class AbstractMethodDeclarationSyntaxNode : MethodDeclarationSyntaxNode internal class AbstractMethodDeclarationSyntaxNode : MethodDeclarationSyntaxNode
{ {
internal readonly FunctionOutputDescriptionSyntaxNode _outputDescription; internal readonly FunctionOutputDescriptionSyntaxNode? _outputDescription;
internal readonly CompoundNameSyntaxNode _name; internal readonly CompoundNameSyntaxNode _name;
internal readonly FunctionInputDescriptionSyntaxNode _inputDescription; internal readonly FunctionInputDescriptionSyntaxNode? _inputDescription;
internal AbstractMethodDeclarationSyntaxNode( internal AbstractMethodDeclarationSyntaxNode(
FunctionOutputDescriptionSyntaxNode outputDescription, FunctionOutputDescriptionSyntaxNode? outputDescription,
CompoundNameSyntaxNode name, CompoundNameSyntaxNode name,
FunctionInputDescriptionSyntaxNode inputDescription) : base(TokenKind.AbstractMethodDeclaration) FunctionInputDescriptionSyntaxNode? inputDescription) : base(TokenKind.AbstractMethodDeclaration)
{ {
Slots = 3; Slots = 3;
this.AdjustWidth(outputDescription); this.AdjustWidth(outputDescription);
_outputDescription = outputDescription; _outputDescription = outputDescription;
@ -1554,7 +1512,7 @@ namespace Parser.Internal
return new Parser.AbstractMethodDeclarationSyntaxNode(parent, this, position); return new Parser.AbstractMethodDeclarationSyntaxNode(parent, this, position);
} }
public override GreenNode GetSlot(int i) public override GreenNode? GetSlot(int i)
{ {
switch (i) switch (i)
{ {
@ -1569,17 +1527,16 @@ namespace Parser.Internal
internal class MethodsListSyntaxNode : SyntaxNode internal class MethodsListSyntaxNode : SyntaxNode
{ {
internal readonly SyntaxToken _methodsKeyword; internal readonly SyntaxToken _methodsKeyword;
internal readonly AttributeListSyntaxNode _attributes; internal readonly AttributeListSyntaxNode? _attributes;
internal readonly SyntaxList _methods; internal readonly SyntaxList _methods;
internal readonly SyntaxToken _endKeyword; internal readonly SyntaxToken _endKeyword;
internal MethodsListSyntaxNode( internal MethodsListSyntaxNode(
SyntaxToken methodsKeyword, SyntaxToken methodsKeyword,
AttributeListSyntaxNode attributes, AttributeListSyntaxNode? attributes,
SyntaxList methods, SyntaxList methods,
SyntaxToken endKeyword) : base(TokenKind.MethodsList) SyntaxToken endKeyword) : base(TokenKind.MethodsList)
{ {
Slots = 4; Slots = 4;
this.AdjustWidth(methodsKeyword); this.AdjustWidth(methodsKeyword);
_methodsKeyword = methodsKeyword; _methodsKeyword = methodsKeyword;
@ -1596,7 +1553,7 @@ namespace Parser.Internal
return new Parser.MethodsListSyntaxNode(parent, this, position); return new Parser.MethodsListSyntaxNode(parent, this, position);
} }
public override GreenNode GetSlot(int i) public override GreenNode? GetSlot(int i)
{ {
switch (i) switch (i)
{ {
@ -1612,17 +1569,16 @@ namespace Parser.Internal
internal class PropertiesListSyntaxNode : SyntaxNode internal class PropertiesListSyntaxNode : SyntaxNode
{ {
internal readonly SyntaxToken _propertiesKeyword; internal readonly SyntaxToken _propertiesKeyword;
internal readonly AttributeListSyntaxNode _attributes; internal readonly AttributeListSyntaxNode? _attributes;
internal readonly SyntaxList _properties; internal readonly SyntaxList _properties;
internal readonly SyntaxToken _endKeyword; internal readonly SyntaxToken _endKeyword;
internal PropertiesListSyntaxNode( internal PropertiesListSyntaxNode(
SyntaxToken propertiesKeyword, SyntaxToken propertiesKeyword,
AttributeListSyntaxNode attributes, AttributeListSyntaxNode? attributes,
SyntaxList properties, SyntaxList properties,
SyntaxToken endKeyword) : base(TokenKind.PropertiesList) SyntaxToken endKeyword) : base(TokenKind.PropertiesList)
{ {
Slots = 4; Slots = 4;
this.AdjustWidth(propertiesKeyword); this.AdjustWidth(propertiesKeyword);
_propertiesKeyword = propertiesKeyword; _propertiesKeyword = propertiesKeyword;
@ -1639,7 +1595,7 @@ namespace Parser.Internal
return new Parser.PropertiesListSyntaxNode(parent, this, position); return new Parser.PropertiesListSyntaxNode(parent, this, position);
} }
public override GreenNode GetSlot(int i) public override GreenNode? GetSlot(int i)
{ {
switch (i) switch (i)
{ {
@ -1661,7 +1617,6 @@ namespace Parser.Internal
SyntaxToken lessSign, SyntaxToken lessSign,
SyntaxList baseClasses) : base(TokenKind.BaseClassList) SyntaxList baseClasses) : base(TokenKind.BaseClassList)
{ {
Slots = 2; Slots = 2;
this.AdjustWidth(lessSign); this.AdjustWidth(lessSign);
_lessSign = lessSign; _lessSign = lessSign;
@ -1674,7 +1629,7 @@ namespace Parser.Internal
return new Parser.BaseClassListSyntaxNode(parent, this, position); return new Parser.BaseClassListSyntaxNode(parent, this, position);
} }
public override GreenNode GetSlot(int i) public override GreenNode? GetSlot(int i)
{ {
switch (i) switch (i)
{ {
@ -1688,21 +1643,20 @@ namespace Parser.Internal
internal class ClassDeclarationSyntaxNode : StatementSyntaxNode internal class ClassDeclarationSyntaxNode : StatementSyntaxNode
{ {
internal readonly SyntaxToken _classdefKeyword; internal readonly SyntaxToken _classdefKeyword;
internal readonly AttributeListSyntaxNode _attributes; internal readonly AttributeListSyntaxNode? _attributes;
internal readonly IdentifierNameSyntaxNode _className; internal readonly IdentifierNameSyntaxNode _className;
internal readonly BaseClassListSyntaxNode _baseClassList; internal readonly BaseClassListSyntaxNode? _baseClassList;
internal readonly SyntaxList _nodes; internal readonly SyntaxList _nodes;
internal readonly SyntaxToken _endKeyword; internal readonly SyntaxToken _endKeyword;
internal ClassDeclarationSyntaxNode( internal ClassDeclarationSyntaxNode(
SyntaxToken classdefKeyword, SyntaxToken classdefKeyword,
AttributeListSyntaxNode attributes, AttributeListSyntaxNode? attributes,
IdentifierNameSyntaxNode className, IdentifierNameSyntaxNode className,
BaseClassListSyntaxNode baseClassList, BaseClassListSyntaxNode? baseClassList,
SyntaxList nodes, SyntaxList nodes,
SyntaxToken endKeyword) : base(TokenKind.ClassDeclaration) SyntaxToken endKeyword) : base(TokenKind.ClassDeclaration)
{ {
Slots = 6; Slots = 6;
this.AdjustWidth(classdefKeyword); this.AdjustWidth(classdefKeyword);
_classdefKeyword = classdefKeyword; _classdefKeyword = classdefKeyword;
@ -1723,7 +1677,7 @@ namespace Parser.Internal
return new Parser.ClassDeclarationSyntaxNode(parent, this, position); return new Parser.ClassDeclarationSyntaxNode(parent, this, position);
} }
public override GreenNode GetSlot(int i) public override GreenNode? GetSlot(int i)
{ {
switch (i) switch (i)
{ {
@ -1749,7 +1703,6 @@ namespace Parser.Internal
SyntaxList values, SyntaxList values,
SyntaxToken closingBracket) : base(TokenKind.EnumerationItemValue) SyntaxToken closingBracket) : base(TokenKind.EnumerationItemValue)
{ {
Slots = 3; Slots = 3;
this.AdjustWidth(openingBracket); this.AdjustWidth(openingBracket);
_openingBracket = openingBracket; _openingBracket = openingBracket;
@ -1764,7 +1717,7 @@ namespace Parser.Internal
return new Parser.EnumerationItemValueSyntaxNode(parent, this, position); return new Parser.EnumerationItemValueSyntaxNode(parent, this, position);
} }
public override GreenNode GetSlot(int i) public override GreenNode? GetSlot(int i)
{ {
switch (i) switch (i)
{ {
@ -1779,15 +1732,14 @@ namespace Parser.Internal
internal class EnumerationItemSyntaxNode : SyntaxNode internal class EnumerationItemSyntaxNode : SyntaxNode
{ {
internal readonly IdentifierNameSyntaxNode _name; internal readonly IdentifierNameSyntaxNode _name;
internal readonly EnumerationItemValueSyntaxNode _values; internal readonly EnumerationItemValueSyntaxNode? _values;
internal readonly SyntaxList<SyntaxToken> _commas; internal readonly SyntaxList<SyntaxToken> _commas;
internal EnumerationItemSyntaxNode( internal EnumerationItemSyntaxNode(
IdentifierNameSyntaxNode name, IdentifierNameSyntaxNode name,
EnumerationItemValueSyntaxNode values, EnumerationItemValueSyntaxNode? values,
SyntaxList<SyntaxToken> commas) : base(TokenKind.EnumerationItem) SyntaxList<SyntaxToken> commas) : base(TokenKind.EnumerationItem)
{ {
Slots = 3; Slots = 3;
this.AdjustWidth(name); this.AdjustWidth(name);
_name = name; _name = name;
@ -1802,7 +1754,7 @@ namespace Parser.Internal
return new Parser.EnumerationItemSyntaxNode(parent, this, position); return new Parser.EnumerationItemSyntaxNode(parent, this, position);
} }
public override GreenNode GetSlot(int i) public override GreenNode? GetSlot(int i)
{ {
switch (i) switch (i)
{ {
@ -1817,17 +1769,16 @@ namespace Parser.Internal
internal class EnumerationListSyntaxNode : SyntaxNode internal class EnumerationListSyntaxNode : SyntaxNode
{ {
internal readonly SyntaxToken _enumerationKeyword; internal readonly SyntaxToken _enumerationKeyword;
internal readonly AttributeListSyntaxNode _attributes; internal readonly AttributeListSyntaxNode? _attributes;
internal readonly SyntaxList<EnumerationItemSyntaxNode> _items; internal readonly SyntaxList<EnumerationItemSyntaxNode> _items;
internal readonly SyntaxToken _endKeyword; internal readonly SyntaxToken _endKeyword;
internal EnumerationListSyntaxNode( internal EnumerationListSyntaxNode(
SyntaxToken enumerationKeyword, SyntaxToken enumerationKeyword,
AttributeListSyntaxNode attributes, AttributeListSyntaxNode? attributes,
SyntaxList<EnumerationItemSyntaxNode> items, SyntaxList<EnumerationItemSyntaxNode> items,
SyntaxToken endKeyword) : base(TokenKind.EnumerationList) SyntaxToken endKeyword) : base(TokenKind.EnumerationList)
{ {
Slots = 4; Slots = 4;
this.AdjustWidth(enumerationKeyword); this.AdjustWidth(enumerationKeyword);
_enumerationKeyword = enumerationKeyword; _enumerationKeyword = enumerationKeyword;
@ -1844,7 +1795,7 @@ namespace Parser.Internal
return new Parser.EnumerationListSyntaxNode(parent, this, position); return new Parser.EnumerationListSyntaxNode(parent, this, position);
} }
public override GreenNode GetSlot(int i) public override GreenNode? GetSlot(int i)
{ {
switch (i) switch (i)
{ {
@ -1860,17 +1811,16 @@ namespace Parser.Internal
internal class EventsListSyntaxNode : SyntaxNode internal class EventsListSyntaxNode : SyntaxNode
{ {
internal readonly SyntaxToken _eventsKeyword; internal readonly SyntaxToken _eventsKeyword;
internal readonly AttributeListSyntaxNode _attributes; internal readonly AttributeListSyntaxNode? _attributes;
internal readonly SyntaxList _events; internal readonly SyntaxList _events;
internal readonly SyntaxToken _endKeyword; internal readonly SyntaxToken _endKeyword;
internal EventsListSyntaxNode( internal EventsListSyntaxNode(
SyntaxToken eventsKeyword, SyntaxToken eventsKeyword,
AttributeListSyntaxNode attributes, AttributeListSyntaxNode? attributes,
SyntaxList events, SyntaxList events,
SyntaxToken endKeyword) : base(TokenKind.EventsList) SyntaxToken endKeyword) : base(TokenKind.EventsList)
{ {
Slots = 4; Slots = 4;
this.AdjustWidth(eventsKeyword); this.AdjustWidth(eventsKeyword);
_eventsKeyword = eventsKeyword; _eventsKeyword = eventsKeyword;
@ -1887,7 +1837,7 @@ namespace Parser.Internal
return new Parser.EventsListSyntaxNode(parent, this, position); return new Parser.EventsListSyntaxNode(parent, this, position);
} }
public override GreenNode GetSlot(int i) public override GreenNode? GetSlot(int i)
{ {
switch (i) switch (i)
{ {
@ -1899,4 +1849,31 @@ namespace Parser.Internal
} }
} }
} }
internal class EndKeywordSyntaxNode : SyntaxNode
{
internal readonly SyntaxToken _endKeyword;
internal EndKeywordSyntaxNode(
SyntaxToken endKeyword) : base(TokenKind.EndKeyword)
{
Slots = 1;
this.AdjustWidth(endKeyword);
_endKeyword = endKeyword;
}
internal override Parser.SyntaxNode CreateRed(Parser.SyntaxNode parent, int position)
{
return new Parser.EndKeywordSyntaxNode(parent, this, position);
}
public override GreenNode? GetSlot(int i)
{
switch (i)
{
case 0: return _endKeyword;
default: return null;
}
}
}
} }

View File

@ -79,4 +79,30 @@ namespace Parser.Internal
{ {
} }
} }
internal class RootSyntaxNode : SyntaxNode
{
internal readonly FileSyntaxNode _file;
public RootSyntaxNode(FileSyntaxNode file) : base(TokenKind.Root)
{
Slots = 1;
this.AdjustWidth(file);
_file = file;
}
public override GreenNode? GetSlot(int i)
{
switch (i)
{
case 0: return _file;
default: return null;
}
}
internal override Parser.SyntaxNode CreateRed(Parser.SyntaxNode parent, int position)
{
return new Parser.RootSyntaxNode(this, position);
}
}
} }

View File

@ -7,7 +7,7 @@ namespace Parser.Internal
{ {
internal abstract class SyntaxToken : GreenNode internal abstract class SyntaxToken : GreenNode
{ {
public TextSpan Span { get; } internal static IReadOnlyList<SyntaxTrivia> s_EmptySyntaxTriviaList = new List<SyntaxTrivia>();
internal class SyntaxTokenWithTrivia : SyntaxToken internal class SyntaxTokenWithTrivia : SyntaxToken
{ {
@ -198,12 +198,14 @@ namespace Parser.Internal
{ {
} }
internal static SyntaxToken NoneToken => new MissingTokenWithTrivia(TokenKind.None, s_EmptySyntaxTriviaList, s_EmptySyntaxTriviaList);
public virtual int Width => Text.Length; public virtual int Width => Text.Length;
public override IReadOnlyList<SyntaxTrivia> LeadingTriviaCore => new List<SyntaxTrivia>(); public override IReadOnlyList<SyntaxTrivia> LeadingTriviaCore => s_EmptySyntaxTriviaList;
public override IReadOnlyList<SyntaxTrivia> TrailingTriviaCore => new List<SyntaxTrivia>(); public override IReadOnlyList<SyntaxTrivia> TrailingTriviaCore => s_EmptySyntaxTriviaList;
public override GreenNode GetSlot(int i) public override GreenNode? GetSlot(int i)
{ {
throw new System.InvalidOperationException(); throw new System.InvalidOperationException();
} }

View File

@ -17,7 +17,7 @@ namespace Parser.Internal
public override string Text => _text; public override string Text => _text;
public int Width => _text.Length; public int Width => _text.Length;
public override GreenNode GetSlot(int i) public override GreenNode? GetSlot(int i)
{ {
throw new System.NotImplementedException(); throw new System.NotImplementedException();
} }

View File

@ -51,10 +51,10 @@ namespace Parser.Internal
public static SyntaxToken CreateMissing( public static SyntaxToken CreateMissing(
TokenKind kind, TokenKind kind,
IReadOnlyList<SyntaxTrivia> leadingTrivia, IReadOnlyList<SyntaxTrivia>? leadingTrivia,
IReadOnlyList<SyntaxTrivia> trailingTrivia) IReadOnlyList<SyntaxTrivia>? trailingTrivia)
{ {
return new SyntaxToken.MissingTokenWithTrivia(kind, leadingTrivia, trailingTrivia); return new SyntaxToken.MissingTokenWithTrivia(kind, leadingTrivia ?? SyntaxToken.s_EmptySyntaxTriviaList, trailingTrivia ?? SyntaxToken.s_EmptySyntaxTriviaList);
} }
} }
} }

View File

@ -20,23 +20,24 @@ namespace Parser
var lexerDiagnostics = lexer.Diagnostics; var lexerDiagnostics = lexer.Diagnostics;
var tokens = lexer.ParseAll(); var tokens = lexer.ParseAll();
var parser = new Internal.MParserGreen(tokens, new Internal.SyntaxFactory()); var parser = new Internal.MParserGreen(tokens, new Internal.SyntaxFactory());
var green = parser.ParseFile(); var green = parser.ParseRoot();
var parserDiagnostics = parser.Diagnostics; var parserDiagnostics = parser.Diagnostics;
var totalDiagnostics = new DiagnosticsBag(lexerDiagnostics.Concat(parserDiagnostics)); var totalDiagnostics = new DiagnosticsBag(lexerDiagnostics.Concat(parserDiagnostics));
var root = new FileSyntaxNode(null, green, 0); var root = new RootSyntaxNode(green, 0);
return new SyntaxTree(root, totalDiagnostics); return new SyntaxTree(root, totalDiagnostics);
} }
} }
public class SyntaxTree public class SyntaxTree
{ {
public SyntaxTree(FileSyntaxNode root, DiagnosticsBag diagnostics) public SyntaxTree(RootSyntaxNode nullRoot, DiagnosticsBag diagnostics)
{ {
Root = root ?? throw new ArgumentNullException(nameof(root)); NullRoot = nullRoot ?? throw new ArgumentNullException(nameof(nullRoot));
Diagnostics = diagnostics ?? throw new ArgumentNullException(nameof(diagnostics)); Diagnostics = diagnostics ?? throw new ArgumentNullException(nameof(diagnostics));
} }
public FileSyntaxNode Root { get; } public RootSyntaxNode NullRoot { get; }
public FileSyntaxNode Root => NullRoot.File;
public DiagnosticsBag Diagnostics { get; } public DiagnosticsBag Diagnostics { get; }
} }

View File

@ -1,6 +1,8 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework> <TargetFramework>netstandard2.0</TargetFramework>
<LangVersion>8.0</LangVersion>
<NullableReferenceTypes>true</NullableReferenceTypes>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="System.Collections.Immutable" Version="1.5.0" /> <PackageReference Include="System.Collections.Immutable" Version="1.5.0" />

View File

@ -2,7 +2,7 @@
{ {
public struct Position public struct Position
{ {
public string FileName { get; set; } public string? FileName { get; set; }
public int Line { get; set; } public int Line { get; set; }
public int Column { get; set; } public int Column { get; set; }
public int Offset { get; set; } public int Offset { get; set; }

File diff suppressed because it is too large Load Diff

View File

@ -15,6 +15,13 @@ namespace Parser
Position = position; Position = position;
} }
private protected SyntaxNode(Internal.GreenNode green, int position)
{
_parent = this;
_green = green;
Position = position;
}
public TokenKind Kind => _green.Kind; public TokenKind Kind => _green.Kind;
public SyntaxNode Parent => _parent; public SyntaxNode Parent => _parent;
@ -43,9 +50,9 @@ namespace Parser
return result; return result;
} }
internal abstract SyntaxNode GetNode(int index); internal abstract SyntaxNode? GetNode(int index);
internal SyntaxNode GetRed(ref SyntaxNode field, int slot) internal SyntaxNode? GetRed(ref SyntaxNode? field, int slot)
{ {
if (field == null) if (field == null)
{ {
@ -119,4 +126,35 @@ namespace Parser
} }
} }
public class RootSyntaxNode : SyntaxNode
{
private SyntaxNode? _file;
internal RootSyntaxNode(Internal.GreenNode green, int position) : base(green, position)
{
}
internal override SyntaxNode? GetNode(int index)
{
throw new System.NotImplementedException();
}
public override void Accept(SyntaxVisitor visitor)
{
throw new System.NotImplementedException();
}
public FileSyntaxNode File
{
get
{
var red = this.GetRed(ref this._file, 0);
if (red != null)
return (FileSyntaxNode)red;
throw new System.Exception("file cannot be null");
}
}
}
} }

View File

@ -2,7 +2,7 @@
{ {
public struct SyntaxNodeOrToken public struct SyntaxNodeOrToken
{ {
private readonly Internal.GreenNode _token; private readonly Internal.GreenNode? _token;
private readonly SyntaxNode _nodeOrParent; private readonly SyntaxNode _nodeOrParent;
private readonly bool _isToken; private readonly bool _isToken;
@ -27,7 +27,7 @@
public int Position { get; } public int Position { get; }
public SyntaxNode AsNode() public SyntaxNode? AsNode()
{ {
if (_isToken) if (_isToken)
{ {
@ -43,7 +43,7 @@
{ {
return default(SyntaxToken); return default(SyntaxToken);
} }
return new SyntaxToken(_nodeOrParent, _token, Position); return new SyntaxToken(_nodeOrParent, _token!, Position);
} }
public static implicit operator SyntaxNodeOrToken(SyntaxToken token) public static implicit operator SyntaxNodeOrToken(SyntaxToken token)

View File

@ -24,7 +24,7 @@ namespace Parser
} }
else else
{ {
return green.CreateRed(this, this.GetChildPosition(index)); return green!.CreateRed(this, this.GetChildPosition(index));
} }
} }
throw new ArgumentOutOfRangeException(); throw new ArgumentOutOfRangeException();
@ -81,7 +81,7 @@ namespace Parser
public int Count => _green.Slots; public int Count => _green.Slots;
internal override SyntaxNode GetNode(int index) internal override SyntaxNode? GetNode(int index)
{ {
if (index < _green.Slots) if (index < _green.Slots)
{ {

View File

@ -251,5 +251,10 @@ namespace Parser
{ {
DefaultVisit(node); DefaultVisit(node);
} }
public virtual void VisitEndKeyword(EndKeywordSyntaxNode node)
{
DefaultVisit(node);
}
} }
}; };

View File

@ -2,7 +2,7 @@
{ {
public abstract partial class SyntaxVisitor public abstract partial class SyntaxVisitor
{ {
public virtual void Visit(SyntaxNode node) public virtual void Visit(SyntaxNode? node)
{ {
node?.Accept(this); node?.Accept(this);
} }

View File

@ -6,7 +6,7 @@
private Position _position; private Position _position;
public Position Position => _position; public Position Position => _position;
public TextWindow(string text, string fileName = null) public TextWindow(string text, string? fileName = null)
{ {
Text = text; Text = text;
_position = new Position _position = new Position

View File

@ -2,7 +2,7 @@
{ {
public class TextWindowWithNull : TextWindow public class TextWindowWithNull : TextWindow
{ {
public TextWindowWithNull(string text, string fileName = null) : base(text, fileName) public TextWindowWithNull(string text, string? fileName = null) : base(text, fileName)
{ {
} }

View File

@ -271,5 +271,7 @@
// ToggleSomething // ToggleSomething
// end // end
EventsList, EventsList,
EndKeyword,
Root
} }
} }

View File

@ -15,7 +15,7 @@ namespace SyntaxGenerator
private static readonly List<(string visitorMethodName, string className)> Visitors = new List<(string, string)>(); private static readonly List<(string visitorMethodName, string className)> Visitors = new List<(string, string)>();
private static string _outputPath; private static readonly string _outputPath;
static GenerateSyntax() static GenerateSyntax()
{ {
@ -62,12 +62,14 @@ namespace SyntaxGenerator
private static string GenerateInternalFieldDeclaration(FieldDescription field) private static string GenerateInternalFieldDeclaration(FieldDescription field)
{ {
return $" internal readonly {field.FieldType} _{field.FieldName};\n"; return $" internal readonly {FullFieldType(field)} _{field.FieldName};\n";
} }
private static string GeneratePrivateFieldDeclaration(FieldDescription field) private static string GeneratePrivateFieldDeclaration(FieldDescription field)
{ {
return $" private SyntaxNode _{field.FieldName};\n"; //var typeDeclaration = field.FieldIsNullable ? "SyntaxNode?" : "SyntaxNode";
var typeDeclaration = "SyntaxNode?";
return $" private {typeDeclaration} _{field.FieldName};\n";
} }
private static string GenerateFieldAssignmentInsideConstructor(FieldDescription field) private static string GenerateFieldAssignmentInsideConstructor(FieldDescription field)
@ -81,15 +83,15 @@ namespace SyntaxGenerator
{ {
var arguments = string.Join( var arguments = string.Join(
",", ",",
node.Fields.Select(field => $"\n {field.FieldType} {field.FieldName}")); node.Fields.Select(field => $"\n {FullFieldType(field)} {field.FieldName}"));
var header = var header =
$" internal {node.ClassName}({arguments}) : base(TokenKind.{node.TokenKindName})\n"; $" internal {node.ClassName}({arguments}) : base(TokenKind.{node.TokenKindName})";
var slotsAssignment = $"\n Slots = {node.Fields.Length};\n"; var slotsAssignment = $" Slots = {node.Fields.Length};";
var assignments = string.Join( var assignments = string.Join(
"", "",
node.Fields.Select(GenerateFieldAssignmentInsideConstructor)); node.Fields.Select(GenerateFieldAssignmentInsideConstructor));
return header + " {\n" + slotsAssignment + assignments + " }\n"; return header + "\n {\n" + slotsAssignment + "\n" + assignments + " }\n";
} }
private static string GenerateConstructor(SyntaxNodeDescription node) private static string GenerateConstructor(SyntaxNodeDescription node)
@ -102,7 +104,7 @@ namespace SyntaxGenerator
private static string GenerateInternalGetSlot(SyntaxNodeDescription node) private static string GenerateInternalGetSlot(SyntaxNodeDescription node)
{ {
var header = $" public override GreenNode GetSlot(int i)\n"; var header = $" public override GreenNode? GetSlot(int i)\n";
var cases = string.Join( var cases = string.Join(
"", "",
node.Fields.Select((f, i) => $" case {i}: return _{f.FieldName};\n")); node.Fields.Select((f, i) => $" case {i}: return _{f.FieldName};\n"));
@ -117,10 +119,16 @@ namespace SyntaxGenerator
private static string GenerateGetSlot(SyntaxNodeDescription node, List<(FieldDescription field, int index)> pairs) private static string GenerateGetSlot(SyntaxNodeDescription node, List<(FieldDescription field, int index)> pairs)
{ {
var header = $" internal override SyntaxNode GetNode(int i)\n"; var header = $" internal override SyntaxNode? GetNode(int i)\n";
string GetFieldNameWithPossibleBang(FieldDescription field)
{
return field.FieldIsNullable ? field.FieldName : field.FieldName + "!";
}
var cases = string.Join( var cases = string.Join(
"", "",
pairs.Select(pair => $" case {pair.index}: return GetRed(ref _{pair.field.FieldName}, {pair.index});\n")); pairs.Select(pair => $" case {pair.index}: return GetRed(ref _{GetFieldNameWithPossibleBang(pair.field)}, {pair.index});\n"));
var defaultCase = " default: return null;\n"; var defaultCase = " default: return null;\n";
return header return header
+ " {\n switch (i)\n {\n" + " {\n switch (i)\n {\n"
@ -185,12 +193,17 @@ namespace SyntaxGenerator
{ {
type = "SyntaxNodeOrTokenList"; type = "SyntaxNodeOrTokenList";
} }
var header = $" public {type} {Capitalize(field.FieldName)}\n {{\n get\n {{\n";
var typeName = type + (field.FieldIsNullable ? "?" : "");
var header = $" public {typeName} {Capitalize(field.FieldName)}\n {{\n get\n {{\n";
var defaultReturnStatement = field.FieldIsNullable ? $"return default({type});" : $"throw new System.Exception(\"{field.FieldName} cannot be null\");";
var fieldNameWithPossibleBang = field.FieldIsNullable ? field.FieldName : field.FieldName + "!";
var text = var text =
$" var red = this.GetRed(ref this._{field.FieldName}, {index});\n" $" var red = this.GetRed(ref this._{fieldNameWithPossibleBang}, {index});\n"
+ $" if (red != null)\n" + $" if (red != null)\n"
+ $" return ({type})red;\n\n" + $" return ({type})red;\n\n"
+ $" return default({type});\n"; + $" {defaultReturnStatement}\n";
return header + text + " }\n }\n"; return header + text + " }\n }\n";
} }
@ -287,13 +300,18 @@ namespace SyntaxGenerator
} }
} }
private static string FullFieldType(FieldDescription field)
{
return field.FieldIsNullable ? field.FieldType + "?" : field.FieldType;
}
private static string GenerateFactoryMethod(SyntaxNodeDescription node) private static string GenerateFactoryMethod(SyntaxNodeDescription node)
{ {
var methodName = FactoryMethodNameFromClassName(node.ClassName); var methodName = FactoryMethodNameFromClassName(node.ClassName);
var header = $" public {node.ClassName} {methodName}"; var header = $" public {node.ClassName} {methodName}";
var arguments = string.Join( var arguments = string.Join(
", ", ", ",
node.Fields.Select(field => $"\n {field.FieldType} {field.FieldName}")); node.Fields.Select(field => $"\n {FullFieldType(field)} {field.FieldName}"));
var constructorParameters = string.Join( var constructorParameters = string.Join(
", ", ", ",
node.Fields.Select(field => $"\n {field.FieldName}")); node.Fields.Select(field => $"\n {field.FieldName}"));
@ -335,8 +353,7 @@ namespace SyntaxGenerator
var serializer = new XmlSerializer(typeof(SyntaxDescription)); var serializer = new XmlSerializer(typeof(SyntaxDescription));
using (var stream = new FileStream("input.xml", FileMode.Open)) using (var stream = new FileStream("input.xml", FileMode.Open))
{ {
var syntax = serializer.Deserialize(stream) as SyntaxDescription; if (!(serializer.Deserialize(stream) is SyntaxDescription syntax))
if (syntax == null)
{ {
Console.WriteLine("Couldn't deserialize syntax."); Console.WriteLine("Couldn't deserialize syntax.");
return; return;

View File

@ -34,5 +34,7 @@ namespace SyntaxGenerator
public string FieldType { get; set; } public string FieldType { get; set; }
[XmlAttribute("Name")] [XmlAttribute("Name")]
public string FieldName { get; set; } public string FieldName { get; set; }
[XmlAttribute("Nullable")]
public bool FieldIsNullable { get; set; }
} }
} }

View File

@ -6,12 +6,12 @@
</Class> </Class>
<Class Name="FunctionDeclarationSyntaxNode" BaseClass="StatementSyntaxNode" Kind="FunctionDeclaration"> <Class Name="FunctionDeclarationSyntaxNode" BaseClass="StatementSyntaxNode" Kind="FunctionDeclaration">
<Field Type="SyntaxToken" Name="functionKeyword" /> <Field Type="SyntaxToken" Name="functionKeyword" />
<Field Type="FunctionOutputDescriptionSyntaxNode" Name="outputDescription" /> <Field Type="FunctionOutputDescriptionSyntaxNode" Name="outputDescription" Nullable="true" />
<Field Type="SyntaxToken" Name="name" /> <Field Type="SyntaxToken" Name="name" />
<Field Type="FunctionInputDescriptionSyntaxNode" Name="inputDescription" /> <Field Type="FunctionInputDescriptionSyntaxNode" Name="inputDescription" Nullable="true"/>
<Field Type="SyntaxList&lt;SyntaxToken&gt;" Name="commas" /> <Field Type="SyntaxList&lt;SyntaxToken&gt;" Name="commas" />
<Field Type="SyntaxList" Name="body" /> <Field Type="SyntaxList" Name="body" />
<Field Type="SyntaxToken" Name="endKeyword" /> <Field Type="EndKeywordSyntaxNode" Name="endKeyword" Nullable="true"/>
</Class> </Class>
<Class Name="FunctionOutputDescriptionSyntaxNode" BaseClass="SyntaxNode" Kind="FunctionOutputDescription"> <Class Name="FunctionOutputDescriptionSyntaxNode" BaseClass="SyntaxNode" Kind="FunctionOutputDescription">
<Field Type="SyntaxList" Name="outputList" /> <Field Type="SyntaxList" Name="outputList" />
@ -58,7 +58,7 @@
<Field Type="SyntaxList&lt;SyntaxToken&gt;" Name="optionalCommas" /> <Field Type="SyntaxList&lt;SyntaxToken&gt;" Name="optionalCommas" />
<Field Type="SyntaxList" Name="body" /> <Field Type="SyntaxList" Name="body" />
<Field Type="SyntaxList&lt;ElseifClause&gt;" Name="elseifClauses" /> <Field Type="SyntaxList&lt;ElseifClause&gt;" Name="elseifClauses" />
<Field Type="ElseClause" Name="elseClause" /> <Field Type="ElseClause" Name="elseClause" Nullable="true" />
<Field Type="SyntaxToken" Name="endKeyword" /> <Field Type="SyntaxToken" Name="endKeyword" />
</Class> </Class>
<Class Name="ForStatementSyntaxNode" BaseClass="StatementSyntaxNode" Kind="ForStatement"> <Class Name="ForStatementSyntaxNode" BaseClass="StatementSyntaxNode" Kind="ForStatement">
@ -80,7 +80,7 @@
<Class Name="TryCatchStatementSyntaxNode" BaseClass="StatementSyntaxNode" Kind="TryCatchStatement"> <Class Name="TryCatchStatementSyntaxNode" BaseClass="StatementSyntaxNode" Kind="TryCatchStatement">
<Field Type="SyntaxToken" Name="tryKeyword" /> <Field Type="SyntaxToken" Name="tryKeyword" />
<Field Type="SyntaxList" Name="tryBody" /> <Field Type="SyntaxList" Name="tryBody" />
<Field Type="CatchClauseSyntaxNode" Name="catchClause" /> <Field Type="CatchClauseSyntaxNode" Name="catchClause" Nullable="true" />
<Field Type="SyntaxToken" Name="endKeyword" /> <Field Type="SyntaxToken" Name="endKeyword" />
</Class> </Class>
<Class Name="ExpressionStatementSyntaxNode" BaseClass="StatementSyntaxNode" Kind="ExpressionStatement"> <Class Name="ExpressionStatementSyntaxNode" BaseClass="StatementSyntaxNode" Kind="ExpressionStatement">
@ -183,7 +183,7 @@
</Class> </Class>
<Class Name="AttributeSyntaxNode" BaseClass="SyntaxNode" Kind="Attribute"> <Class Name="AttributeSyntaxNode" BaseClass="SyntaxNode" Kind="Attribute">
<Field Type="IdentifierNameSyntaxNode" Name="name" /> <Field Type="IdentifierNameSyntaxNode" Name="name" />
<Field Type="AttributeAssignmentSyntaxNode" Name="assignment" /> <Field Type="AttributeAssignmentSyntaxNode" Name="assignment" Nullable="true" />
</Class> </Class>
<Class Name="AttributeListSyntaxNode" BaseClass="SyntaxNode" Kind="AttributeList"> <Class Name="AttributeListSyntaxNode" BaseClass="SyntaxNode" Kind="AttributeList">
<Field Type="SyntaxToken" Name="openingBracket" /> <Field Type="SyntaxToken" Name="openingBracket" />
@ -192,27 +192,27 @@
</Class> </Class>
<Class Name="MethodDefinitionSyntaxNode" BaseClass="MethodDeclarationSyntaxNode" Kind="MethodDefinition"> <Class Name="MethodDefinitionSyntaxNode" BaseClass="MethodDeclarationSyntaxNode" Kind="MethodDefinition">
<Field Type="SyntaxToken" Name="functionKeyword" /> <Field Type="SyntaxToken" Name="functionKeyword" />
<Field Type="FunctionOutputDescriptionSyntaxNode" Name="outputDescription" /> <Field Type="FunctionOutputDescriptionSyntaxNode" Name="outputDescription" Nullable="true" />
<Field Type="CompoundNameSyntaxNode" Name="name" /> <Field Type="CompoundNameSyntaxNode" Name="name" />
<Field Type="FunctionInputDescriptionSyntaxNode" Name="inputDescription" /> <Field Type="FunctionInputDescriptionSyntaxNode" Name="inputDescription" Nullable="true"/>
<Field Type="SyntaxList&lt;SyntaxToken&gt;" Name="commas" /> <Field Type="SyntaxList&lt;SyntaxToken&gt;" Name="commas" />
<Field Type="SyntaxList" Name="body" /> <Field Type="SyntaxList" Name="body" />
<Field Type="SyntaxToken" Name="endKeyword" /> <Field Type="EndKeywordSyntaxNode" Name="endKeyword" Nullable="true" />
</Class> </Class>
<Class Name="AbstractMethodDeclarationSyntaxNode" BaseClass="MethodDeclarationSyntaxNode" Kind="AbstractMethodDeclaration"> <Class Name="AbstractMethodDeclarationSyntaxNode" BaseClass="MethodDeclarationSyntaxNode" Kind="AbstractMethodDeclaration">
<Field Type="FunctionOutputDescriptionSyntaxNode" Name="outputDescription" /> <Field Type="FunctionOutputDescriptionSyntaxNode" Name="outputDescription" Nullable="true" />
<Field Type="CompoundNameSyntaxNode" Name="name" /> <Field Type="CompoundNameSyntaxNode" Name="name" />
<Field Type="FunctionInputDescriptionSyntaxNode" Name="inputDescription" /> <Field Type="FunctionInputDescriptionSyntaxNode" Name="inputDescription" Nullable="true"/>
</Class> </Class>
<Class Name="MethodsListSyntaxNode" BaseClass="SyntaxNode" Kind="MethodsList"> <Class Name="MethodsListSyntaxNode" BaseClass="SyntaxNode" Kind="MethodsList">
<Field Type="SyntaxToken" Name="methodsKeyword" /> <Field Type="SyntaxToken" Name="methodsKeyword" />
<Field Type="AttributeListSyntaxNode" Name="attributes" /> <Field Type="AttributeListSyntaxNode" Name="attributes" Nullable="true" />
<Field Type="SyntaxList" Name="methods" /> <Field Type="SyntaxList" Name="methods" />
<Field Type="SyntaxToken" Name="endKeyword" /> <Field Type="SyntaxToken" Name="endKeyword" />
</Class> </Class>
<Class Name="PropertiesListSyntaxNode" BaseClass="SyntaxNode" Kind="PropertiesList"> <Class Name="PropertiesListSyntaxNode" BaseClass="SyntaxNode" Kind="PropertiesList">
<Field Type="SyntaxToken" Name="propertiesKeyword" /> <Field Type="SyntaxToken" Name="propertiesKeyword" />
<Field Type="AttributeListSyntaxNode" Name="attributes" /> <Field Type="AttributeListSyntaxNode" Name="attributes" Nullable="true" />
<Field Type="SyntaxList" Name="properties" /> <Field Type="SyntaxList" Name="properties" />
<Field Type="SyntaxToken" Name="endKeyword" /> <Field Type="SyntaxToken" Name="endKeyword" />
</Class> </Class>
@ -222,9 +222,9 @@
</Class> </Class>
<Class Name="ClassDeclarationSyntaxNode" BaseClass="StatementSyntaxNode" Kind="ClassDeclaration"> <Class Name="ClassDeclarationSyntaxNode" BaseClass="StatementSyntaxNode" Kind="ClassDeclaration">
<Field Type="SyntaxToken" Name="classdefKeyword" /> <Field Type="SyntaxToken" Name="classdefKeyword" />
<Field Type="AttributeListSyntaxNode" Name="attributes" /> <Field Type="AttributeListSyntaxNode" Name="attributes" Nullable="true" />
<Field Type="IdentifierNameSyntaxNode" Name="className" /> <Field Type="IdentifierNameSyntaxNode" Name="className" />
<Field Type="BaseClassListSyntaxNode" Name="baseClassList" /> <Field Type="BaseClassListSyntaxNode" Name="baseClassList" Nullable="true" />
<Field Type="SyntaxList" Name="nodes" /> <Field Type="SyntaxList" Name="nodes" />
<Field Type="SyntaxToken" Name="endKeyword" /> <Field Type="SyntaxToken" Name="endKeyword" />
</Class> </Class>
@ -235,19 +235,22 @@
</Class> </Class>
<Class Name="EnumerationItemSyntaxNode" BaseClass="SyntaxNode" Kind="EnumerationItem"> <Class Name="EnumerationItemSyntaxNode" BaseClass="SyntaxNode" Kind="EnumerationItem">
<Field Type="IdentifierNameSyntaxNode" Name="name" /> <Field Type="IdentifierNameSyntaxNode" Name="name" />
<Field Type="EnumerationItemValueSyntaxNode" Name="values" /> <Field Type="EnumerationItemValueSyntaxNode" Name="values" Nullable="true"/>
<Field Type="SyntaxList&lt;SyntaxToken&gt;" Name="commas" /> <Field Type="SyntaxList&lt;SyntaxToken&gt;" Name="commas" />
</Class> </Class>
<Class Name="EnumerationListSyntaxNode" BaseClass="SyntaxNode" Kind="EnumerationList"> <Class Name="EnumerationListSyntaxNode" BaseClass="SyntaxNode" Kind="EnumerationList">
<Field Type="SyntaxToken" Name="enumerationKeyword" /> <Field Type="SyntaxToken" Name="enumerationKeyword" />
<Field Type="AttributeListSyntaxNode" Name="attributes" /> <Field Type="AttributeListSyntaxNode" Name="attributes" Nullable="true"/>
<Field Type="SyntaxList&lt;EnumerationItemSyntaxNode&gt;" Name="items" /> <Field Type="SyntaxList&lt;EnumerationItemSyntaxNode&gt;" Name="items" />
<Field Type="SyntaxToken" Name="endKeyword" /> <Field Type="SyntaxToken" Name="endKeyword" />
</Class> </Class>
<Class Name="EventsListSyntaxNode" BaseClass="SyntaxNode" Kind="EventsList"> <Class Name="EventsListSyntaxNode" BaseClass="SyntaxNode" Kind="EventsList">
<Field Type="SyntaxToken" Name="eventsKeyword" /> <Field Type="SyntaxToken" Name="eventsKeyword" />
<Field Type="AttributeListSyntaxNode" Name="attributes" /> <Field Type="AttributeListSyntaxNode" Name="attributes" Nullable="true" />
<Field Type="SyntaxList" Name="events" /> <Field Type="SyntaxList" Name="events" />
<Field Type="SyntaxToken" Name="endKeyword" /> <Field Type="SyntaxToken" Name="endKeyword" />
</Class> </Class>
<Class Name="EndKeywordSyntaxNode" BaseClass="SyntaxNode" Kind="EndKeyword">
<Field Type="SyntaxToken" Name="endKeyword" />
</Class>
</Syntax> </Syntax>