Handle if else if (else) statements

This commit is contained in:
Deukhoofd 2018-11-13 15:15:44 +01:00
parent 56f3777053
commit b9aac52476
No known key found for this signature in database
GPG Key ID: B4C087AC81641654
6 changed files with 120 additions and 26 deletions

View File

@ -105,7 +105,7 @@ namespace Upsilon.Binder
type = Type.Number;
outValue = new NumberLong(l);
break;
case bool b:
case bool _:
type = Type.Boolean;
outValue = value;
break;
@ -180,6 +180,12 @@ namespace Upsilon.Binder
{
var condition = BindExpressionStatement(e.Condition);
var block = BindBlockStatement(e.Block);
if (e.NextElseIfStatement != null)
{
var nextElseIf = BindIfStatement(e.NextElseIfStatement);
return new BoundIfStatement((BoundExpressionStatement) condition, (BoundBlockStatement) block,
(BoundIfStatement) nextElseIf);
}
if (e.ElseStatement == null)
{
return new BoundIfStatement((BoundExpressionStatement) condition, (BoundBlockStatement) block);

View File

@ -7,17 +7,25 @@ namespace Upsilon.Binder
Condition = condition;
Block = block;
}
public BoundIfStatement(BoundExpressionStatement condition, BoundBlockStatement block, BoundElseStatement elseStatement)
{
Condition = condition;
Block = block;
ElseStatement = elseStatement;
}
public BoundIfStatement(BoundExpressionStatement condition, BoundBlockStatement block, BoundIfStatement nextElseIf)
{
Condition = condition;
Block = block;
NextElseIf = nextElseIf;
}
public override BoundKind Kind => BoundKind.BoundIfStatement;
public BoundExpressionStatement Condition { get; }
public BoundBlockStatement Block { get; }
public BoundIfStatement NextElseIf { get; }
public BoundElseStatement ElseStatement { get; }
}

View File

@ -138,6 +138,10 @@ namespace Upsilon.Evaluator
{
EvaluateBoundBlockStatement(boundBlockStatement.Block);
}
else if (boundBlockStatement.NextElseIf != null)
{
EvaluateBoundIfStatement(boundBlockStatement.NextElseIf);
}
else if (boundBlockStatement.ElseStatement != null)
{
EvaluateBoundBlockStatement(boundBlockStatement.ElseStatement.Block);

View File

@ -68,11 +68,7 @@ namespace Upsilon.Parser
}
if (Current.Kind == SyntaxKind.IfKeyword)
{
return ParseIfStatement();
}
if (Current.Kind == SyntaxKind.ElseKeyword)
{
Console.WriteLine("Here");
return ParseIfStatement(SyntaxKind.IfKeyword);
}
return ParseExpressionStatement();
@ -89,26 +85,32 @@ namespace Upsilon.Parser
return new BlockStatementSyntax(statements.ToImmutable());
}
private StatementSyntax ParseIfStatement()
private StatementSyntax ParseIfStatement(SyntaxKind requiredToken)
{
var ifToken = MatchToken(SyntaxKind.IfKeyword);
var ifToken = MatchToken(requiredToken);
var condition = ParseExpressionStatement();
var thenToken = MatchToken(SyntaxKind.ThenKeyword);
var block = ParseBlockStatement(new []{SyntaxKind.EndKeyword, SyntaxKind.ElseIfKeyword, SyntaxKind.ElseKeyword});
var endToken = NextToken();
switch (endToken.Kind)
switch (Current.Kind)
{
case SyntaxKind.EndKeyword:
return new IfStatementSyntax(ifToken, condition, thenToken, (BlockStatementSyntax) block, endToken);
case SyntaxKind.ElseIfKeyword:
var nextElseIf =
new ElseIfStatementSyntax((IfStatementSyntax) ParseIfStatement(SyntaxKind.ElseIfKeyword));
return new IfStatementSyntax(ifToken, condition, thenToken, (BlockStatementSyntax) block,
nextElseIf);
case SyntaxKind.ElseKeyword:
{
var elseToken = MatchToken(SyntaxKind.ElseKeyword);
var elseBlock = ParseBlockStatement(new[]{SyntaxKind.EndKeyword});
var endEndToken = MatchToken(SyntaxKind.EndKeyword);
var elseStatement = new ElseStatementSyntax(endToken, (BlockStatementSyntax) elseBlock, endEndToken);
var elseStatement = new ElseStatementSyntax(elseToken, (BlockStatementSyntax) elseBlock, endEndToken);
return new IfStatementSyntax(ifToken, condition, thenToken, (BlockStatementSyntax) block, elseStatement);
}
case SyntaxKind.EndKeyword:
var endToken = MatchToken(SyntaxKind.EndKeyword);
return new IfStatementSyntax(ifToken, condition, thenToken, (BlockStatementSyntax) block, endToken);
default:
return null;
throw new ArgumentOutOfRangeException();
}
}

View File

@ -1,9 +1,12 @@
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using Upsilon.Text;
namespace Upsilon.Parser
{
public sealed class IfStatementSyntax : StatementSyntax
public class IfStatementSyntax : StatementSyntax
{
public IfStatementSyntax(SyntaxToken ifToken, ExpressionStatementSyntax condition, SyntaxToken thenToken,
BlockStatementSyntax block, SyntaxToken endToken)
@ -14,7 +17,6 @@ namespace Upsilon.Parser
Block = block;
EndToken = endToken;
Span = new TextSpan(ifToken.Span.Start, endToken.Span.End);
}
public IfStatementSyntax(SyntaxToken ifToken, ExpressionStatementSyntax condition, SyntaxToken thenToken,
@ -26,7 +28,16 @@ namespace Upsilon.Parser
Block = block;
ElseStatement = elseStatement;
Span = new TextSpan(ifToken.Span.Start, elseStatement.Span.End);
}
public IfStatementSyntax(SyntaxToken ifToken, ExpressionStatementSyntax condition, SyntaxToken thenToken,
BlockStatementSyntax block, ElseIfStatementSyntax nextElseIfStatement)
{
IfToken = ifToken;
Condition = condition;
ThenToken = thenToken;
Block = block;
NextElseIfStatement = nextElseIfStatement;
}
@ -34,7 +45,8 @@ namespace Upsilon.Parser
public ExpressionStatementSyntax Condition { get; }
public SyntaxToken ThenToken { get; }
public BlockStatementSyntax Block { get; }
public ElseStatementSyntax ElseStatement { get; }
public ElseIfStatementSyntax NextElseIfStatement { get; protected set; }
public ElseStatementSyntax ElseStatement { get; protected set; }
public SyntaxToken EndToken { get; }
public override SyntaxKind Kind => SyntaxKind.IfStatement;
@ -44,13 +56,54 @@ namespace Upsilon.Parser
yield return Condition;
yield return ThenToken;
yield return Block;
if (EndToken != null)
yield return EndToken;
if (NextElseIfStatement != null)
yield return NextElseIfStatement;
if (ElseStatement != null)
yield return ElseStatement;
if (EndToken != null)
yield return EndToken;
}
}
public sealed class ElseIfStatementSyntax : IfStatementSyntax
{
public SyntaxToken ElseIfToken => IfToken;
public override SyntaxKind Kind => SyntaxKind.ElseIfStatement;
public override IEnumerable<SyntaxNode> ChildNodes()
{
yield return ElseIfToken;
yield return Condition;
yield return ThenToken;
yield return Block;
}
public ElseIfStatementSyntax(IfStatementSyntax s)
:base(s.IfToken, s.Condition, s.ThenToken, s.Block, s.EndToken)
{
NextElseIfStatement = s.NextElseIfStatement;
ElseStatement = s.ElseStatement;
}
public ElseIfStatementSyntax(SyntaxToken ifToken, ExpressionStatementSyntax condition, SyntaxToken thenToken,
BlockStatementSyntax block, SyntaxToken endToken) : base(ifToken, condition, thenToken, block, endToken)
{
}
public ElseIfStatementSyntax(SyntaxToken ifToken, ExpressionStatementSyntax condition, SyntaxToken thenToken,
BlockStatementSyntax block, ElseStatementSyntax elseStatement) : base(ifToken, condition, thenToken, block,
elseStatement)
{
}
public ElseIfStatementSyntax(SyntaxToken ifToken, ExpressionStatementSyntax condition, SyntaxToken thenToken,
BlockStatementSyntax block, ElseIfStatementSyntax nextElseIfStatement) : base(ifToken, condition, thenToken,
block, nextElseIfStatement)
{
}
}
public sealed class ElseStatementSyntax : StatementSyntax
{
public SyntaxToken ElseToken { get; }

View File

@ -34,5 +34,26 @@ end";
var actual = (long)(NumberLong)script.Evaluate();
Assert.Equal(expected, actual);
}
[Theory]
[InlineData("true", "false", 3, 8, 5, 3)]
[InlineData("false", "true", 3, 8, 5, 8)]
public void BasicIfElseIfElseTests(string condition1, string condition2, int in1, int in2, int in3, long expected)
{
var input =
$@"
if {condition1} then
val = {in1}
elseif {condition2} then
val = {in2}
else
val = {in3}
end";
var script = new Script(input);
Assert.Empty(script.Diagnostics.Messages);
var actual = (long)(NumberLong)script.Evaluate();
Assert.Equal(expected, actual);
}
}
}