Upsilon/Upsilon/Parser/Parser.cs

604 lines
25 KiB
C#
Raw Permalink Normal View History

2018-11-13 11:48:50 +00:00
using System;
using System.Collections.Generic;
2018-11-10 12:11:36 +00:00
using System.Collections.Immutable;
2018-11-13 12:54:51 +00:00
using System.Linq;
2018-11-10 12:11:36 +00:00
namespace Upsilon.Parser
{
public class Parser
{
private readonly ImmutableArray<SyntaxToken> _tokens;
2018-11-11 09:26:52 +00:00
private readonly Diagnostics _diagnostics;
2018-11-10 12:11:36 +00:00
private int _position;
2018-11-11 09:26:52 +00:00
private Parser(ImmutableArray<SyntaxToken> tokens, Diagnostics diagnostics)
2018-11-10 12:11:36 +00:00
{
_tokens = tokens;
2018-11-11 09:26:52 +00:00
_diagnostics = diagnostics;
2018-11-10 12:11:36 +00:00
}
public static BlockStatementSyntax Parse(string text, Diagnostics diagnostics, bool saveComments)
2018-11-10 12:11:36 +00:00
{
var tokens = Lexer.Lex(text, diagnostics, saveComments);
return (BlockStatementSyntax) new Parser(tokens, diagnostics).ParseScriptSyntax();
2018-11-10 12:11:36 +00:00
}
private SyntaxToken Current => Get(0);
private SyntaxToken Next => Get(1);
2018-11-26 12:59:57 +00:00
private SyntaxToken Get(int offset)
2018-11-10 12:11:36 +00:00
{
2018-11-26 12:42:50 +00:00
if (_position + offset >= _tokens.Length)
return new SyntaxToken(SyntaxKind.EndOfFile, _tokens.Last().Span, null);
2018-11-26 12:42:50 +00:00
else
{
2018-11-26 12:59:57 +00:00
return _tokens[_position + offset];
2018-11-26 12:42:50 +00:00
}
2018-11-10 12:11:36 +00:00
}
private SyntaxToken NextToken()
{
var current = Current;
_position++;
return current;
}
private SyntaxToken MatchToken(SyntaxKind kind)
{
if (Current.Kind == kind)
return NextToken();
2018-11-15 14:51:05 +00:00
_diagnostics.LogBadCharacter(Current.Span, kind, Current.Kind);
return new SyntaxToken(kind, Current.Span, null);
2018-11-10 12:11:36 +00:00
}
2018-11-13 12:54:51 +00:00
private StatementSyntax ParseScriptSyntax()
2018-11-10 12:11:36 +00:00
{
2018-11-13 12:54:51 +00:00
var statement = ParseBlockStatement(new []{SyntaxKind.EndOfFile});
2018-11-13 11:48:50 +00:00
MatchToken(SyntaxKind.EndOfFile);
return statement;
2018-11-10 12:11:36 +00:00
}
2018-11-13 12:54:51 +00:00
private StatementSyntax ParseStatement()
2018-11-10 12:11:36 +00:00
{
2018-11-10 16:00:39 +00:00
if (Current.Kind == SyntaxKind.Identifier && Next.Kind == SyntaxKind.Equals)
{
return ParseAssignmentExpression();
2018-11-10 16:00:39 +00:00
}
if (Current.Kind == SyntaxKind.LocalKeyword && Next.Kind == SyntaxKind.Identifier)
{
return ParseAssignmentExpression();
2018-11-10 16:00:39 +00:00
}
2018-11-13 11:48:50 +00:00
if (Current.Kind == SyntaxKind.IfKeyword)
{
2018-11-13 14:15:44 +00:00
return ParseIfStatement(SyntaxKind.IfKeyword);
2018-11-13 12:54:51 +00:00
}
if (Current.Kind == SyntaxKind.ReturnKeyword)
2018-11-15 14:51:05 +00:00
{
return ParseReturnStatement();
2018-11-15 14:51:05 +00:00
}
if (Current.Kind == SyntaxKind.FunctionKeyword && Next.Kind != SyntaxKind.OpenParenthesis)
2018-11-15 14:51:05 +00:00
{
2019-02-13 17:10:39 +00:00
return ParseFunctionAssignmentStatement(SyntaxKind.FunctionKeyword);
2018-11-15 14:51:05 +00:00
}
if (Current.Kind == SyntaxKind.LocalKeyword && Next.Kind == SyntaxKind.FunctionKeyword)
2018-11-16 12:45:03 +00:00
{
2019-02-13 17:10:39 +00:00
return ParseFunctionAssignmentStatement(SyntaxKind.FunctionKeyword);
}
if (Current.Kind == SyntaxKind.CoroutineKeyword && Next.Kind != SyntaxKind.OpenParenthesis)
{
return ParseFunctionAssignmentStatement(SyntaxKind.CoroutineKeyword);
}
if (Current.Kind == SyntaxKind.LocalKeyword && Next.Kind == SyntaxKind.CoroutineKeyword)
{
return ParseFunctionAssignmentStatement(SyntaxKind.CoroutineKeyword);
2018-11-16 12:45:03 +00:00
}
2018-11-23 13:38:45 +00:00
if (Current.Kind == SyntaxKind.ForKeyword)
{
return ParseForStatement();
}
2018-12-07 18:17:49 +00:00
if (Current.Kind == SyntaxKind.WhileKeyword)
{
return ParseWhileStatement();
}
2018-11-23 14:27:48 +00:00
if (Current.Kind == SyntaxKind.BreakKeyword)
{
return new BreakStatementSyntax(NextToken());
}
2019-02-13 17:10:39 +00:00
if (Current.Kind == SyntaxKind.YieldKeyword)
{
return ParseYieldStatement();
}
2018-11-15 14:51:05 +00:00
return ParseExpressionStatement();
}
2018-11-13 12:54:51 +00:00
private StatementSyntax ParseBlockStatement(SyntaxKind[] endTokens)
{
var statements = ImmutableArray.CreateBuilder<StatementSyntax>();
SyntaxToken current = null;
2018-11-25 20:50:18 +00:00
while (!endTokens.Contains(Current.Kind) && Current.Kind != SyntaxKind.EndOfFile)
{
if (current == Current)
{
break;
}
current = Current;
var next = ParseStatement();
statements.Add(next);
}
2018-11-13 11:48:50 +00:00
return new BlockStatementSyntax(statements.ToImmutable());
}
2018-11-13 14:15:44 +00:00
private StatementSyntax ParseIfStatement(SyntaxKind requiredToken)
2018-11-13 11:48:50 +00:00
{
2018-11-13 14:15:44 +00:00
var ifToken = MatchToken(requiredToken);
2018-11-13 11:48:50 +00:00
var condition = ParseExpressionStatement();
var thenToken = MatchToken(SyntaxKind.ThenKeyword);
2018-11-13 12:54:51 +00:00
var block = ParseBlockStatement(new []{SyntaxKind.EndKeyword, SyntaxKind.ElseIfKeyword, SyntaxKind.ElseKeyword});
2018-11-13 14:15:44 +00:00
switch (Current.Kind)
2018-11-13 12:54:51 +00:00
{
2018-11-13 14:15:44 +00:00
case SyntaxKind.ElseIfKeyword:
var nextElseIf =
new ElseIfStatementSyntax((IfStatementSyntax) ParseIfStatement(SyntaxKind.ElseIfKeyword));
2018-11-19 15:22:13 +00:00
return new IfStatementSyntax(ifToken, (ExpressionStatementSyntax) condition, thenToken, (BlockStatementSyntax) block,
2018-11-13 14:15:44 +00:00
nextElseIf);
2018-11-13 12:54:51 +00:00
case SyntaxKind.ElseKeyword:
{
2018-11-13 14:15:44 +00:00
var elseToken = MatchToken(SyntaxKind.ElseKeyword);
2018-11-13 12:54:51 +00:00
var elseBlock = ParseBlockStatement(new[]{SyntaxKind.EndKeyword});
var endEndToken = MatchToken(SyntaxKind.EndKeyword);
2018-11-13 14:15:44 +00:00
var elseStatement = new ElseStatementSyntax(elseToken, (BlockStatementSyntax) elseBlock, endEndToken);
2018-11-19 15:22:13 +00:00
return new IfStatementSyntax(ifToken, (ExpressionStatementSyntax) condition, thenToken, (BlockStatementSyntax) block, elseStatement);
2018-11-13 12:54:51 +00:00
}
2018-11-13 14:15:44 +00:00
case SyntaxKind.EndKeyword:
var endToken = MatchToken(SyntaxKind.EndKeyword);
2018-11-19 15:22:13 +00:00
return new IfStatementSyntax(ifToken, (ExpressionStatementSyntax) condition, thenToken, (BlockStatementSyntax) block, endToken);
2018-11-13 12:54:51 +00:00
default:
2018-11-13 14:15:44 +00:00
throw new ArgumentOutOfRangeException();
2018-11-13 12:54:51 +00:00
}
}
2018-11-23 13:38:45 +00:00
private StatementSyntax ParseForStatement()
{
var forToken = MatchToken(SyntaxKind.ForKeyword);
if (Next.Kind == SyntaxKind.Equals)
{
return ParseNumericForStatement(forToken);
}
return ParseGenericForStatement(forToken);
}
private StatementSyntax ParseNumericForStatement(SyntaxToken forToken)
{
var identifier = (IdentifierToken)MatchToken(SyntaxKind.Identifier);
var equals = MatchToken(SyntaxKind.Equals);
var v1 = ParseExpression();
var comma1 = MatchToken(SyntaxKind.Comma);
var v2 = ParseExpression();
SyntaxToken comma2 = null;
ExpressionSyntax v3 = null;
if (Current.Kind == SyntaxKind.Comma)
{
comma2 = MatchToken(SyntaxKind.Comma);
v3 = ParseExpression();
}
var doToken = MatchToken(SyntaxKind.DoKeyword);
var block = ParseBlockStatement(new []{SyntaxKind.EndKeyword});
var endToken = MatchToken(SyntaxKind.EndKeyword);
2018-11-23 17:18:07 +00:00
return new NumericForStatementSyntax(forToken, identifier, equals, v1, comma1,
v2, comma2, v3, doToken, block, endToken);
2018-11-23 13:38:45 +00:00
}
private StatementSyntax ParseGenericForStatement(SyntaxToken forToken)
{
2018-11-23 17:18:07 +00:00
var arr = ImmutableArray.CreateBuilder<IdentifierToken>();
while (true)
{
var identifier = MatchToken(SyntaxKind.Identifier);
arr.Add((IdentifierToken) identifier);
if (Current.Kind == SyntaxKind.InKeyword || Current.Kind == SyntaxKind.EndOfFile)
2018-11-23 17:18:07 +00:00
break;
MatchToken(SyntaxKind.Comma);
}
var inKeyword = MatchToken(SyntaxKind.InKeyword);
var enumerableExpression = ParseExpression();
var doKeyword = MatchToken(SyntaxKind.DoKeyword);
var block = ParseBlockStatement(new[] {SyntaxKind.EndKeyword});
var endKeyword = MatchToken(SyntaxKind.EndKeyword);
return new GenericForStatementSyntax(forToken, arr.ToImmutable(), inKeyword, enumerableExpression,
doKeyword, (BlockStatementSyntax) block, endKeyword);
2018-11-23 13:38:45 +00:00
}
2018-12-07 18:17:49 +00:00
private StatementSyntax ParseWhileStatement()
{
var whileToken = MatchToken(SyntaxKind.WhileKeyword);
var expression = ParseExpression();
var doToken = MatchToken(SyntaxKind.DoKeyword);
var block = ParseBlockStatement(new[] {SyntaxKind.EndKeyword});
var endKeyword = MatchToken(SyntaxKind.EndKeyword);
return new WhileStatementSyntax(whileToken, expression, doToken, block, endKeyword);
}
2019-02-13 17:10:39 +00:00
private ExpressionSyntax ParseFunctionExpression(SyntaxKind openKeyword)
{
2019-02-13 17:10:39 +00:00
var functionToken = MatchToken(openKeyword);
var openParenthesis = MatchToken(SyntaxKind.OpenParenthesis);
var variableBuilder = ImmutableArray.CreateBuilder<ParameterToken>();
SyntaxToken current = null;
while (Current.Kind != SyntaxKind.CloseParenthesis)
{
if (Current == current)
{
break;
}
current = Current;
var firstToken = MatchToken(SyntaxKind.Identifier);
if (Current.Kind == SyntaxKind.Identifier)
{
variableBuilder.Add(new ParameterToken((IdentifierToken) firstToken,
(IdentifierToken) NextToken()));
}
else
{
variableBuilder.Add(new ParameterToken(null, (IdentifierToken) firstToken));
}
if (Current.Kind == SyntaxKind.Comma)
NextToken();
}
var closeParenthesis = MatchToken(SyntaxKind.CloseParenthesis);
var block = ParseBlockStatement(new[] {SyntaxKind.EndKeyword});
var endToken = MatchToken(SyntaxKind.EndKeyword);
2019-02-13 17:10:39 +00:00
var isCoroutine = openKeyword == SyntaxKind.CoroutineKeyword;
return new FunctionExpressionSyntax(functionToken, openParenthesis,
2019-02-13 17:10:39 +00:00
variableBuilder.ToImmutable(), closeParenthesis, (BlockStatementSyntax) block, endToken, isCoroutine);
}
2019-02-13 17:10:39 +00:00
private StatementSyntax ParseFunctionAssignmentStatement(SyntaxKind identifyingKeyword)
2018-11-15 14:51:05 +00:00
{
SyntaxToken localToken = null;
string[] commentData = null;
2018-11-15 14:51:05 +00:00
if (Current.Kind == SyntaxKind.LocalKeyword)
{
localToken = NextToken();
commentData = localToken.CommentData;
2018-11-15 14:51:05 +00:00
}
2019-02-13 17:10:39 +00:00
var functionToken = MatchToken(identifyingKeyword);
if (commentData == null)
{
commentData = functionToken.CommentData;
}
var identifier = MatchToken(SyntaxKind.Identifier);
2018-11-15 14:51:05 +00:00
var openParenthesis = MatchToken(SyntaxKind.OpenParenthesis);
var variableBuilder = ImmutableArray.CreateBuilder<ParameterToken>();
while (Current.Kind != SyntaxKind.CloseParenthesis || Current.Kind == SyntaxKind.EndOfFile)
2018-11-15 14:51:05 +00:00
{
var firstToken = MatchToken(SyntaxKind.Identifier);
if (Current.Kind == SyntaxKind.Identifier)
{
variableBuilder.Add(new ParameterToken((IdentifierToken) firstToken,
(IdentifierToken) NextToken()));
}
else
{
variableBuilder.Add(new ParameterToken(null, (IdentifierToken) firstToken));
}
2018-11-15 14:51:05 +00:00
if (Current.Kind == SyntaxKind.Comma)
NextToken();
}
var closeParenthesis = MatchToken(SyntaxKind.CloseParenthesis);
var block = ParseBlockStatement(new[] {SyntaxKind.EndKeyword});
var endToken = MatchToken(SyntaxKind.EndKeyword);
2019-02-13 17:10:39 +00:00
var isCoroutine = identifyingKeyword == SyntaxKind.CoroutineKeyword;
var functionExpression = new FunctionExpressionSyntax(functionToken, openParenthesis,
2019-02-13 17:10:39 +00:00
variableBuilder.ToImmutable(), closeParenthesis, (BlockStatementSyntax) block, endToken, isCoroutine);
return new FunctionAssignmentStatementSyntax(localToken, (IdentifierToken) identifier, functionExpression)
{
CommentData = commentData
};
2018-11-15 14:51:05 +00:00
}
2018-11-19 15:22:13 +00:00
private StatementSyntax ParseExpressionStatement()
{
var expression = ParseExpression();
2018-11-19 15:22:13 +00:00
if (expression.Kind == SyntaxKind.IndexExpression && Current.Kind == SyntaxKind.Equals)
{
return ParseTableAssignmentExpression(expression);
}
if (expression.Kind == SyntaxKind.FullStopIndexExpression && Current.Kind == SyntaxKind.Equals)
{
return ParseTableAssignmentExpression(expression);
}
return new ExpressionStatementSyntax(expression);
}
2018-11-16 12:45:03 +00:00
private StatementSyntax ParseReturnStatement()
{
2018-11-28 13:31:40 +00:00
var returnToken = (ReturnSyntaxToken)MatchToken(SyntaxKind.ReturnKeyword);
2018-11-28 13:13:39 +00:00
ExpressionSyntax expression = null;
2018-11-28 13:31:40 +00:00
if (Current.Kind != SyntaxKind.EndKeyword && !returnToken.FollowedByLineBreak)
2018-11-28 13:13:39 +00:00
expression = ParseExpression();
2018-11-16 12:45:03 +00:00
return new ReturnStatementSyntax(returnToken, expression);
}
2019-02-13 17:10:39 +00:00
private StatementSyntax ParseYieldStatement()
{
var yieldToken = MatchToken(SyntaxKind.YieldKeyword);
var expression = ParseExpression();
return new YieldStatementSyntax(yieldToken, expression);
}
2018-11-13 12:54:51 +00:00
private ExpressionSyntax ParseExpression()
{
ExpressionSyntax expression;
if (Current.Kind == SyntaxKind.FunctionKeyword && Next.Kind == SyntaxKind.OpenParenthesis)
{
2019-02-13 17:10:39 +00:00
expression = ParseFunctionExpression(SyntaxKind.FunctionKeyword);
}
else if (Current.Kind == SyntaxKind.CoroutineKeyword && Next.Kind == SyntaxKind.OpenParenthesis)
{
expression = ParseFunctionExpression(SyntaxKind.FunctionKeyword);
}
else
{
expression = ParseBinaryExpression();
}
expression = HandleComplexExpression(expression);
return expression;
}
private ExpressionSyntax HandleComplexExpression(ExpressionSyntax baseExpression)
{
SyntaxToken current = null;
while (Current.Kind == SyntaxKind.OpenBracket || Current.Kind == SyntaxKind.OpenParenthesis ||
Current.Kind == SyntaxKind.FullStop)
{
if (Current == current)
break;
current = Current;
2018-11-18 19:20:03 +00:00
if (Current.Kind == SyntaxKind.OpenBracket)
baseExpression = ParseIndexExpression(baseExpression);
2018-11-18 19:20:03 +00:00
else if (Current.Kind == SyntaxKind.OpenParenthesis)
baseExpression = ParseFunctionCallExpression(baseExpression);
else if (Current.Kind == SyntaxKind.FullStop)
baseExpression = ParseFullStopIndexExpression(baseExpression);
}
return baseExpression;
2018-11-10 12:11:36 +00:00
}
private StatementSyntax ParseAssignmentExpression()
2018-11-10 16:00:39 +00:00
{
string[] commentData = null;
2018-11-10 16:00:39 +00:00
SyntaxToken localKeyword = null;
if (Current.Kind == SyntaxKind.LocalKeyword)
{
localKeyword = MatchToken(SyntaxKind.LocalKeyword);
commentData = localKeyword.CommentData;
2018-11-10 16:00:39 +00:00
}
2018-11-19 15:22:13 +00:00
var identifier = ParseExpression();
if (commentData == null && identifier.Kind == SyntaxKind.VariableExpression)
{
var variable = (VariableExpressionSyntax)identifier;
commentData = variable.Identifier.CommentData;
}
if (Current.Kind == SyntaxKind.Comma)
{
if (identifier.Kind != SyntaxKind.VariableExpression)
{
_diagnostics.LogError("Only identifiers can be used for a multi assignment statement.", identifier.Span);
return new ExpressionStatementSyntax(new BadExpressionSyntax(identifier.Span));
}
var cast = (VariableExpressionSyntax)identifier;
var ls = new List<IdentifierToken>(){cast.Identifier};
while (Current.Kind == SyntaxKind.Comma)
{
NextToken();
ls.Add((IdentifierToken) MatchToken(SyntaxKind.Identifier));
}
var assignmentTokenMulti = MatchToken(SyntaxKind.Equals);
var expressionMulti = ParseExpression();
return new MultiAssignmentStatementSyntax(localKeyword, ls, assignmentTokenMulti, expressionMulti);
}
2018-11-10 16:00:39 +00:00
var assignmentToken = MatchToken(SyntaxKind.Equals);
var expression = ParseExpression();
return new AssignmentStatementSyntax(localKeyword, identifier, assignmentToken, expression)
{
CommentData = commentData
};
2018-11-10 16:00:39 +00:00
}
2018-11-19 15:22:13 +00:00
private StatementSyntax ParseTableAssignmentExpression(ExpressionSyntax tableExpression)
{
var assignmentToken = MatchToken(SyntaxKind.Equals);
var expression = ParseExpression();
return new TableAssigmentStatementSyntax(tableExpression, assignmentToken, expression);
}
2018-11-10 12:11:36 +00:00
private ExpressionSyntax ParseBinaryExpression(SyntaxKindPrecedence.Precedence parentPrecedence = SyntaxKindPrecedence.Precedence.None)
{
ExpressionSyntax left;
var unaryOperatorPrecedence = Current.Kind.UnaryOperatorPrecedence();
if (unaryOperatorPrecedence != SyntaxKindPrecedence.Precedence.None
&& unaryOperatorPrecedence >= parentPrecedence)
{
var operatorToken = NextToken();
var operand = ParseBinaryExpression(unaryOperatorPrecedence);
left = new UnaryExpressionSyntax(operatorToken, operand);
}
else
{
left = ParsePrimaryExpression();
}
left = HandleComplexExpression(left);
2018-11-10 12:11:36 +00:00
while (true)
{
var precedence = Current.Kind.BinaryOperatorPrecedence();
if (precedence == SyntaxKindPrecedence.Precedence.None || precedence <= parentPrecedence)
break;
var op = NextToken();
var right = ParseBinaryExpression(precedence);
right = HandleComplexExpression(right);
2018-11-10 12:11:36 +00:00
left = new BinaryExpressionSyntax(left, op, right);
}
return left;
}
private ExpressionSyntax ParsePrimaryExpression()
{
ExpressionSyntax expression;
2018-11-10 12:11:36 +00:00
switch (Current.Kind)
{
case SyntaxKind.OpenParenthesis:
expression = ParseParenthesizedExpression();
break;
2018-11-10 12:11:36 +00:00
case SyntaxKind.Number:
expression = ParseNumber();
break;
2018-11-10 12:11:36 +00:00
case SyntaxKind.TrueKeyword:
case SyntaxKind.FalseKeyword:
expression = ParseBoolean();
break;
2018-11-17 14:57:26 +00:00
case SyntaxKind.String:
expression = ParseString();
break;
2018-11-10 16:00:39 +00:00
case SyntaxKind.Identifier:
expression = ParseVariableExpression();
break;
2018-11-17 18:13:05 +00:00
case SyntaxKind.OpenBrace:
expression = ParseTable();
break;
2018-11-14 12:45:49 +00:00
case SyntaxKind.NilKeyword:
var nilToken = MatchToken(SyntaxKind.NilKeyword);
expression = new LiteralExpressionSyntax(nilToken, null);
break;
2018-11-10 12:11:36 +00:00
default:
2018-12-07 18:29:09 +00:00
_diagnostics.LogBadCharacter(Current.Span);
expression = new BadExpressionSyntax(Current.Span);
2018-11-11 09:26:52 +00:00
NextToken();
break;
2018-11-10 12:11:36 +00:00
}
return expression;
2018-11-10 12:11:36 +00:00
}
private ExpressionSyntax ParseVariableExpression()
{
var token = (IdentifierToken)MatchToken(SyntaxKind.Identifier);
return new VariableExpressionSyntax(token);
}
2018-11-18 19:20:03 +00:00
private ExpressionSyntax ParseFunctionCallExpression(ExpressionSyntax expression)
2018-11-15 19:13:53 +00:00
{
var openParenthesis = MatchToken(SyntaxKind.OpenParenthesis);
var parameters = ImmutableArray.CreateBuilder<ExpressionSyntax>();
SyntaxToken current = null;
2018-11-25 21:06:20 +00:00
while (Current.Kind != SyntaxKind.CloseParenthesis && Current.Kind != SyntaxKind.EndOfFile)
2018-11-15 19:13:53 +00:00
{
if (Current == current)
{
break;
}
current = Current;
2018-11-15 19:13:53 +00:00
var exp = ParseExpression();
parameters.Add(exp);
if (Current.Kind == SyntaxKind.Comma)
NextToken();
}
var closeParenthesis = MatchToken(SyntaxKind.CloseParenthesis);
2018-11-18 19:20:03 +00:00
return new FunctionCallExpressionSyntax(expression, openParenthesis,
2018-11-15 19:13:53 +00:00
parameters.ToImmutable(), closeParenthesis);
}
private ExpressionSyntax ParseIndexExpression(ExpressionSyntax expression)
2018-11-18 13:18:24 +00:00
{
var openBracket = MatchToken(SyntaxKind.OpenBracket);
var index = ParseExpression();
2018-11-18 13:18:24 +00:00
var closeBracket = MatchToken(SyntaxKind.CloseBracket);
return new IndexExpressionSyntax(expression, openBracket, index, closeBracket);
2018-11-18 13:18:24 +00:00
}
private ExpressionSyntax ParseFullStopIndexExpression(ExpressionSyntax expression)
{
var fullStop = MatchToken(SyntaxKind.FullStop);
if (Current.Kind == SyntaxKind.Identifier)
{
var index = NextToken();
return new FullStopIndexExpressionSyntax(expression, fullStop, (IdentifierToken) index);
}
_diagnostics.LogBadCharacter(expression.Span, SyntaxKind.Identifier);
// We'll still want to return a index expression, but we just express that the identifier is empty.
// This is helpful for tools, etc
return new FullStopIndexExpressionSyntax(expression, fullStop,
new IdentifierToken(string.Empty, fullStop.Span));
}
2018-11-10 12:11:36 +00:00
private ExpressionSyntax ParseParenthesizedExpression()
{
var l = MatchToken(SyntaxKind.OpenParenthesis);
var e = ParseExpression();
var r = MatchToken(SyntaxKind.CloseParenthesis);
return new ParenthesizedExpressionSyntax(l, e, r);
}
private ExpressionSyntax ParseNumber()
{
var numberToken = MatchToken(SyntaxKind.Number);
return new LiteralExpressionSyntax(numberToken, numberToken.Value);
}
private ExpressionSyntax ParseBoolean()
{
var isTrue = Current.Kind == SyntaxKind.TrueKeyword;
var token = MatchToken(isTrue ? SyntaxKind.TrueKeyword : SyntaxKind.FalseKeyword);
return new LiteralExpressionSyntax(token, isTrue);
}
2018-11-17 14:57:26 +00:00
private ExpressionSyntax ParseString()
{
var stringToken = MatchToken(SyntaxKind.String);
return new LiteralExpressionSyntax(stringToken, stringToken.Value);
}
2018-11-17 18:13:05 +00:00
private ExpressionSyntax ParseTable()
{
var openBrace = MatchToken(SyntaxKind.OpenBrace);
var arrBuilder = ImmutableArray.CreateBuilder<SyntaxNode>();
bool lastCommaFound = true;
SyntaxToken current = null;
2018-11-17 18:13:05 +00:00
while (Current.Kind != SyntaxKind.CloseBrace)
{
if (!lastCommaFound)
break;
if (Current == current)
{
break;
}
current = Current;
2018-11-17 18:18:54 +00:00
var parsed = ParseStatement();
SyntaxNode node = parsed;
2018-11-17 18:18:54 +00:00
arrBuilder.Add(node);
2018-11-17 18:13:05 +00:00
lastCommaFound = Current.Kind == SyntaxKind.Comma;
if (lastCommaFound) NextToken();
}
var closeBrace = MatchToken(SyntaxKind.CloseBrace);
return new TableExpressionSyntax(openBrace, arrBuilder.ToImmutable(), closeBrace);
}
2018-11-10 12:11:36 +00:00
}
}