2018-11-13 11:48:50 +00:00
|
|
|
using System;
|
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-11 09:26:52 +00:00
|
|
|
using Upsilon.Text;
|
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
|
|
|
}
|
|
|
|
|
2018-11-12 16:45:50 +00:00
|
|
|
public static BlockStatementSyntax Parse(string text, Diagnostics diagnostics)
|
2018-11-10 12:11:36 +00:00
|
|
|
{
|
2018-11-11 09:26:52 +00:00
|
|
|
var tokens = Lexer.Lex(text, diagnostics);
|
2018-11-12 16:45:50 +00:00
|
|
|
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);
|
|
|
|
|
|
|
|
private SyntaxToken Get(int offset)
|
|
|
|
{
|
2018-11-17 13:49:26 +00:00
|
|
|
return _position + offset >= _tokens.Length
|
|
|
|
? new SyntaxToken(SyntaxKind.EndOfFile, _position + offset, "\0", null)
|
|
|
|
: _tokens[_position + offset];
|
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);
|
2018-11-10 12:11:36 +00:00
|
|
|
return new SyntaxToken(kind, Current.Span.Start, "", null);
|
|
|
|
}
|
|
|
|
|
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);
|
2018-11-12 16:45:50 +00:00
|
|
|
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)
|
|
|
|
{
|
2018-11-12 15:21:59 +00:00
|
|
|
return ParseAssignmentExpression();
|
2018-11-10 16:00:39 +00:00
|
|
|
}
|
|
|
|
if (Current.Kind == SyntaxKind.LocalKeyword && Next.Kind == SyntaxKind.Identifier)
|
|
|
|
{
|
2018-11-12 15:21:59 +00:00
|
|
|
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
|
|
|
}
|
2018-11-18 21:22:30 +00:00
|
|
|
if (Current.Kind == SyntaxKind.ReturnKeyword)
|
2018-11-15 14:51:05 +00:00
|
|
|
{
|
2018-11-18 21:22:30 +00:00
|
|
|
return ParseReturnStatement();
|
2018-11-15 14:51:05 +00:00
|
|
|
}
|
2018-11-18 21:22:30 +00:00
|
|
|
if (Current.Kind == SyntaxKind.FunctionKeyword && Next.Kind != SyntaxKind.OpenParenthesis)
|
2018-11-15 14:51:05 +00:00
|
|
|
{
|
2018-11-18 21:22:30 +00:00
|
|
|
return ParseFunctionAssignmentStatement();
|
2018-11-15 14:51:05 +00:00
|
|
|
}
|
2018-11-18 21:22:30 +00:00
|
|
|
if (Current.Kind == SyntaxKind.LocalKeyword && Next.Kind == SyntaxKind.FunctionKeyword)
|
2018-11-16 12:45:03 +00:00
|
|
|
{
|
2018-11-18 21:22:30 +00:00
|
|
|
return ParseFunctionAssignmentStatement();
|
2018-11-16 12:45:03 +00:00
|
|
|
}
|
2018-11-15 14:51:05 +00:00
|
|
|
|
2018-11-12 15:21:59 +00:00
|
|
|
return ParseExpressionStatement();
|
|
|
|
}
|
|
|
|
|
2018-11-13 12:54:51 +00:00
|
|
|
private StatementSyntax ParseBlockStatement(SyntaxKind[] endTokens)
|
2018-11-12 16:45:50 +00:00
|
|
|
{
|
|
|
|
var statements = ImmutableArray.CreateBuilder<StatementSyntax>();
|
2018-11-13 12:54:51 +00:00
|
|
|
while (!endTokens.Contains(Current.Kind))
|
2018-11-12 16:45:50 +00:00
|
|
|
{
|
|
|
|
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-12 16:45:50 +00:00
|
|
|
}
|
|
|
|
|
2018-11-18 21:22:30 +00:00
|
|
|
private ExpressionSyntax ParseFunctionExpression()
|
|
|
|
{
|
|
|
|
var functionToken = MatchToken(SyntaxKind.FunctionKeyword);
|
|
|
|
var openParenthesis = MatchToken(SyntaxKind.OpenParenthesis);
|
|
|
|
var variableBuilder = ImmutableArray.CreateBuilder<IdentifierToken>();
|
|
|
|
while (Current.Kind != SyntaxKind.CloseParenthesis)
|
|
|
|
{
|
|
|
|
var variableIdentifier = (IdentifierToken)MatchToken(SyntaxKind.Identifier);
|
|
|
|
variableBuilder.Add(variableIdentifier);
|
|
|
|
if (Current.Kind == SyntaxKind.Comma)
|
|
|
|
NextToken();
|
|
|
|
}
|
|
|
|
var closeParenthesis = MatchToken(SyntaxKind.CloseParenthesis);
|
|
|
|
var block = ParseBlockStatement(new[] {SyntaxKind.EndKeyword});
|
|
|
|
var endToken = MatchToken(SyntaxKind.EndKeyword);
|
|
|
|
return new FunctionExpressionSyntax(functionToken, openParenthesis,
|
|
|
|
variableBuilder.ToImmutable(), closeParenthesis, (BlockStatementSyntax) block, endToken);
|
|
|
|
}
|
|
|
|
|
|
|
|
private StatementSyntax ParseFunctionAssignmentStatement()
|
2018-11-15 14:51:05 +00:00
|
|
|
{
|
|
|
|
SyntaxToken localToken = null;
|
|
|
|
if (Current.Kind == SyntaxKind.LocalKeyword)
|
|
|
|
{
|
|
|
|
localToken = NextToken();
|
|
|
|
}
|
2018-11-18 21:22:30 +00:00
|
|
|
var functionToken = MatchToken(SyntaxKind.FunctionKeyword);
|
|
|
|
var identifier = (IdentifierToken)MatchToken(SyntaxKind.Identifier);
|
2018-11-15 14:51:05 +00:00
|
|
|
var openParenthesis = MatchToken(SyntaxKind.OpenParenthesis);
|
|
|
|
var variableBuilder = ImmutableArray.CreateBuilder<IdentifierToken>();
|
|
|
|
while (Current.Kind != SyntaxKind.CloseParenthesis)
|
|
|
|
{
|
|
|
|
var variableIdentifier = (IdentifierToken)MatchToken(SyntaxKind.Identifier);
|
|
|
|
variableBuilder.Add(variableIdentifier);
|
|
|
|
if (Current.Kind == SyntaxKind.Comma)
|
|
|
|
NextToken();
|
|
|
|
}
|
|
|
|
var closeParenthesis = MatchToken(SyntaxKind.CloseParenthesis);
|
2018-11-18 21:22:30 +00:00
|
|
|
var block = ParseBlockStatement(new[] {SyntaxKind.EndKeyword});
|
|
|
|
var endToken = MatchToken(SyntaxKind.EndKeyword);
|
|
|
|
var functionExpression = new FunctionExpressionSyntax(functionToken, openParenthesis,
|
2018-11-15 14:51:05 +00:00
|
|
|
variableBuilder.ToImmutable(), closeParenthesis, (BlockStatementSyntax) block, endToken);
|
2018-11-18 21:22:30 +00:00
|
|
|
return new FunctionAssignmentStatementSyntax(localToken, identifier, functionExpression);
|
2018-11-15 14:51:05 +00:00
|
|
|
}
|
|
|
|
|
2018-11-19 15:22:13 +00:00
|
|
|
private StatementSyntax ParseExpressionStatement()
|
2018-11-12 15:21:59 +00:00
|
|
|
{
|
|
|
|
var expression = ParseExpression();
|
2018-11-19 15:22:13 +00:00
|
|
|
if (expression.Kind == SyntaxKind.IndexExpression && Current.Kind == SyntaxKind.Equals)
|
|
|
|
{
|
|
|
|
return ParseTableAssignmentExpression(expression);
|
|
|
|
}
|
2018-11-20 13:05:34 +00:00
|
|
|
if (expression.Kind == SyntaxKind.FullStopIndexExpression && Current.Kind == SyntaxKind.Equals)
|
|
|
|
{
|
|
|
|
return ParseTableAssignmentExpression(expression);
|
|
|
|
}
|
2018-11-12 15:21:59 +00:00
|
|
|
return new ExpressionStatementSyntax(expression);
|
|
|
|
}
|
|
|
|
|
2018-11-16 12:45:03 +00:00
|
|
|
private StatementSyntax ParseReturnStatement()
|
|
|
|
{
|
|
|
|
var returnToken = MatchToken(SyntaxKind.ReturnKeyword);
|
|
|
|
var expression = ParseExpression();
|
|
|
|
return new ReturnStatementSyntax(returnToken, expression);
|
|
|
|
}
|
|
|
|
|
2018-11-13 12:54:51 +00:00
|
|
|
private ExpressionSyntax ParseExpression()
|
2018-11-12 15:21:59 +00:00
|
|
|
{
|
2018-11-18 21:22:30 +00:00
|
|
|
ExpressionSyntax expression;
|
|
|
|
if (Current.Kind == SyntaxKind.FunctionKeyword && Next.Kind == SyntaxKind.OpenParenthesis)
|
|
|
|
{
|
|
|
|
expression = ParseFunctionExpression();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
expression = ParseBinaryExpression();
|
|
|
|
}
|
2018-11-20 13:05:34 +00:00
|
|
|
while (Current.Kind == SyntaxKind.OpenBracket || Current.Kind == SyntaxKind.OpenParenthesis ||
|
|
|
|
Current.Kind == SyntaxKind.FullStop)
|
2018-11-18 15:08:20 +00:00
|
|
|
{
|
2018-11-18 19:20:03 +00:00
|
|
|
if (Current.Kind == SyntaxKind.OpenBracket)
|
|
|
|
expression = ParseIndexExpression(expression);
|
|
|
|
else if (Current.Kind == SyntaxKind.OpenParenthesis)
|
|
|
|
expression = ParseFunctionCallExpression(expression);
|
2018-11-20 13:05:34 +00:00
|
|
|
else if (Current.Kind == SyntaxKind.FullStop)
|
|
|
|
expression = ParseFullStopIndexExpression(expression);
|
2018-11-18 15:08:20 +00:00
|
|
|
}
|
|
|
|
return expression;
|
2018-11-10 12:11:36 +00:00
|
|
|
}
|
|
|
|
|
2018-11-12 15:21:59 +00:00
|
|
|
private AssignmentExpressionSyntax ParseAssignmentExpression()
|
2018-11-10 16:00:39 +00:00
|
|
|
{
|
|
|
|
SyntaxToken localKeyword = null;
|
|
|
|
if (Current.Kind == SyntaxKind.LocalKeyword)
|
|
|
|
{
|
|
|
|
localKeyword = MatchToken(SyntaxKind.LocalKeyword);
|
|
|
|
}
|
2018-11-19 15:22:13 +00:00
|
|
|
|
|
|
|
var identifier = ParseExpression();
|
2018-11-10 16:00:39 +00:00
|
|
|
var assignmentToken = MatchToken(SyntaxKind.Equals);
|
|
|
|
var expression = ParseExpression();
|
|
|
|
return new AssignmentExpressionSyntax(localKeyword, identifier, assignmentToken, expression);
|
|
|
|
}
|
|
|
|
|
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();
|
|
|
|
}
|
|
|
|
|
|
|
|
while (true)
|
|
|
|
{
|
|
|
|
var precedence = Current.Kind.BinaryOperatorPrecedence();
|
|
|
|
if (precedence == SyntaxKindPrecedence.Precedence.None || precedence <= parentPrecedence)
|
|
|
|
break;
|
|
|
|
|
|
|
|
var op = NextToken();
|
|
|
|
var right = ParseBinaryExpression(precedence);
|
|
|
|
left = new BinaryExpressionSyntax(left, op, right);
|
|
|
|
}
|
|
|
|
return left;
|
|
|
|
}
|
|
|
|
|
|
|
|
private ExpressionSyntax ParsePrimaryExpression()
|
|
|
|
{
|
2018-11-18 15:08:20 +00:00
|
|
|
ExpressionSyntax expression;
|
2018-11-10 12:11:36 +00:00
|
|
|
switch (Current.Kind)
|
|
|
|
{
|
|
|
|
case SyntaxKind.OpenParenthesis:
|
2018-11-18 15:08:20 +00:00
|
|
|
expression = ParseParenthesizedExpression();
|
|
|
|
break;
|
2018-11-10 12:11:36 +00:00
|
|
|
case SyntaxKind.Number:
|
2018-11-18 15:08:20 +00:00
|
|
|
expression = ParseNumber();
|
|
|
|
break;
|
2018-11-10 12:11:36 +00:00
|
|
|
case SyntaxKind.TrueKeyword:
|
|
|
|
case SyntaxKind.FalseKeyword:
|
2018-11-18 15:08:20 +00:00
|
|
|
expression = ParseBoolean();
|
|
|
|
break;
|
2018-11-17 14:57:26 +00:00
|
|
|
case SyntaxKind.String:
|
2018-11-18 15:08:20 +00:00
|
|
|
expression = ParseString();
|
|
|
|
break;
|
2018-11-10 16:00:39 +00:00
|
|
|
case SyntaxKind.Identifier:
|
2018-11-18 19:20:03 +00:00
|
|
|
var token = MatchToken(SyntaxKind.Identifier);
|
|
|
|
expression = new VariableExpressionSyntax((IdentifierToken) token);
|
2018-11-18 15:08:20 +00:00
|
|
|
break;
|
2018-11-17 18:13:05 +00:00
|
|
|
case SyntaxKind.OpenBrace:
|
2018-11-18 15:08:20 +00:00
|
|
|
expression = ParseTable();
|
|
|
|
break;
|
2018-11-14 12:45:49 +00:00
|
|
|
case SyntaxKind.NilKeyword:
|
|
|
|
var nilToken = MatchToken(SyntaxKind.NilKeyword);
|
2018-11-18 15:08:20 +00:00
|
|
|
expression = new LiteralExpressionSyntax(nilToken, null);
|
|
|
|
break;
|
2018-11-10 12:11:36 +00:00
|
|
|
default:
|
2018-11-19 15:22:13 +00:00
|
|
|
_diagnostics.LogBadCharacter(new TextSpan(_position, 1));
|
2018-11-11 09:26:52 +00:00
|
|
|
NextToken();
|
2018-11-18 15:08:20 +00:00
|
|
|
expression = new BadExpressionSyntax();
|
|
|
|
break;
|
2018-11-10 12:11:36 +00:00
|
|
|
}
|
2018-11-18 15:08:20 +00:00
|
|
|
return expression;
|
2018-11-10 12:11:36 +00:00
|
|
|
}
|
|
|
|
|
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>();
|
|
|
|
while (Current.Kind != SyntaxKind.CloseParenthesis)
|
|
|
|
{
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2018-11-18 15:08:20 +00:00
|
|
|
private ExpressionSyntax ParseIndexExpression(ExpressionSyntax expression)
|
2018-11-18 13:18:24 +00:00
|
|
|
{
|
2018-11-20 13:05:34 +00:00
|
|
|
var openBracket = MatchToken(SyntaxKind.OpenBracket);
|
|
|
|
var index = ParseExpression();
|
2018-11-18 13:18:24 +00:00
|
|
|
var closeBracket = MatchToken(SyntaxKind.CloseBracket);
|
2018-11-18 15:08:20 +00:00
|
|
|
return new IndexExpressionSyntax(expression, openBracket, index, closeBracket);
|
2018-11-18 13:18:24 +00:00
|
|
|
}
|
|
|
|
|
2018-11-20 13:05:34 +00:00
|
|
|
private ExpressionSyntax ParseFullStopIndexExpression(ExpressionSyntax expression)
|
|
|
|
{
|
|
|
|
var fullStop = MatchToken(SyntaxKind.FullStop);
|
|
|
|
var index = MatchToken(SyntaxKind.Identifier);
|
|
|
|
if (index is IdentifierToken identifier)
|
|
|
|
{
|
|
|
|
return new FullStopIndexExpressionSyntax(expression, fullStop, identifier);
|
|
|
|
}
|
|
|
|
_diagnostics.LogBadCharacter(expression.Span, SyntaxKind.Identifier);
|
|
|
|
return new BadExpressionSyntax();
|
|
|
|
}
|
|
|
|
|
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;
|
|
|
|
while (Current.Kind != SyntaxKind.CloseBrace)
|
|
|
|
{
|
|
|
|
if (!lastCommaFound)
|
|
|
|
break;
|
2018-11-17 18:18:54 +00:00
|
|
|
var parsed = ParseStatement();
|
2018-11-17 18:45:24 +00:00
|
|
|
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
|
|
|
}
|
|
|
|
}
|