Skip to content

Commit

Permalink
#304 - Parse 'if' as expression
Browse files Browse the repository at this point in the history
  • Loading branch information
sys27 committed Oct 9, 2020
1 parent 8f33214 commit 76af849
Show file tree
Hide file tree
Showing 4 changed files with 53 additions and 37 deletions.
2 changes: 1 addition & 1 deletion xFunc.Maths/Expressions/Programming/If.cs
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ public override object Execute(ExpressionParameters? parameters)
if (condition)
return Then.Execute(parameters);

return Else?.Execute(parameters) ?? 0.0;
return Else?.Execute(parameters) ?? new NumberValue(0.0);
}

throw new ResultIsNotSupportedException(this, result);
Expand Down
70 changes: 35 additions & 35 deletions xFunc.Maths/Parser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,6 @@ public IExpression Parse(string function)
ParseAssign(ref tokenReader) ??
ParseDef(ref tokenReader) ??
ParseUndef(ref tokenReader) ??
ParseIf(ref tokenReader) ??
ParseFor(ref tokenReader) ??
ParseWhile(ref tokenReader) ??
ParseExpression(ref tokenReader);
Expand Down Expand Up @@ -165,38 +164,6 @@ public IExpression Parse(string function)
return new Undefine(key);
}

private IExpression? ParseIf(ref TokenReader tokenReader)
{
var @if = tokenReader.GetCurrent(IfKeyword);
if (@if.IsEmpty())
return null;

if (!tokenReader.Check(OpenParenthesisSymbol))
MissingOpenParenthesis(@if.Kind);

var condition = ParseConditionalOrOperator(ref tokenReader) ??
throw new ParseException(Resource.IfConditionParseException);

if (!tokenReader.Check(CommaSymbol))
MissingComma(condition);

var then = ParseExpression(ref tokenReader) ??
throw new ParseException(Resource.IfThenParseException);

IExpression? @else = null;
if (tokenReader.Check(CommaSymbol))
@else = ParseExpression(ref tokenReader) ??
throw new ParseException(Resource.IfElseParseException);

if (!tokenReader.Check(CloseParenthesisSymbol))
MissingCloseParenthesis(@if.Kind);

if (@else is not null)
return new If(condition, then, @else);

return new If(condition, then);
}

private IExpression? ParseFor(ref TokenReader tokenReader)
{
var @for = tokenReader.GetCurrent(ForKeyword);
Expand Down Expand Up @@ -288,7 +255,7 @@ public IExpression Parse(string function)

private IExpression? ParseExpression(ref TokenReader tokenReader)
=> ParseBinaryAssign(ref tokenReader) ??
Ternary(ref tokenReader);
ParseTernary(ref tokenReader);

private IExpression? ParseBinaryAssign(ref TokenReader tokenReader)
=> tokenReader.Scoped(this, (Parser parser, ref TokenReader reader) =>
Expand All @@ -313,7 +280,7 @@ public IExpression Parse(string function)
return parser.CreateBinaryAssign(@operator, variable, exp);
});

private IExpression? Ternary(ref TokenReader tokenReader)
private IExpression? ParseTernary(ref TokenReader tokenReader)
=> tokenReader.Scoped(this, (Parser parser, ref TokenReader reader) =>
{
var condition = parser.ParseConditionalOrOperator(ref reader);
Expand Down Expand Up @@ -677,12 +644,45 @@ public IExpression Parse(string function)
private IExpression? ParseOperand(ref TokenReader tokenReader)
=> ParseComplexNumber(ref tokenReader) ??
ParseNumber(ref tokenReader) ??
ParseIf(ref tokenReader) ??
ParseFunctionOrVariable(ref tokenReader) ??
ParseBoolean(ref tokenReader) ??
ParseParenthesesExpression(ref tokenReader) ??
ParseMatrix(ref tokenReader) ??
ParseVector(ref tokenReader);

private IExpression? ParseIf(ref TokenReader tokenReader)
{
var @if = tokenReader.GetCurrent(IfKeyword);
if (@if.IsEmpty())
return null;

if (!tokenReader.Check(OpenParenthesisSymbol))
MissingOpenParenthesis(@if.Kind);

var condition = ParseConditionalOrOperator(ref tokenReader) ??
throw new ParseException(Resource.IfConditionParseException);

if (!tokenReader.Check(CommaSymbol))
MissingComma(condition);

var then = ParseExpression(ref tokenReader) ??
throw new ParseException(Resource.IfThenParseException);

IExpression? @else = null;
if (tokenReader.Check(CommaSymbol))
@else = ParseExpression(ref tokenReader) ??
throw new ParseException(Resource.IfElseParseException);

if (!tokenReader.Check(CloseParenthesisSymbol))
MissingCloseParenthesis(@if.Kind);

if (@else is not null)
return new If(condition, then, @else);

return new If(condition, then);
}

private IExpression? ParseParenthesesExpression(ref TokenReader tokenReader)
{
if (!tokenReader.Check(OpenParenthesisSymbol))
Expand Down
3 changes: 2 additions & 1 deletion xFunc.Tests/Expressions/Programming/IfTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,9 @@ public void CalculateElseTest()

var cond = new Equal(Variable.X, new Number(10));
var @if = new If(cond, new Number(20));
var expected = new NumberValue(0.0);

Assert.Equal(0.0, @if.Execute(parameters));
Assert.Equal(expected, @if.Execute(parameters));
}

[Fact]
Expand Down
15 changes: 15 additions & 0 deletions xFunc.Tests/ParserTests/IfTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,21 @@ public void IfThenElseTest()
ParseTest("if(x == 0 && y != 0, 2, 8)", expected);
}

[Fact]
public void IfThenElseAsExpressionTest()
{
var expected = new Add(
Number.One,
new If(
new Equal(Variable.X, Number.Zero),
Number.Two,
new Number(8)
)
);

ParseTest("1 + if(x == 0, 2, 8)", expected);
}

[Fact]
public void IfThenTest()
{
Expand Down

0 comments on commit 76af849

Please sign in to comment.