Skip to content

Commit

Permalink
#304 - Parse Inc/Dec as expression
Browse files Browse the repository at this point in the history
  • Loading branch information
sys27 committed Sep 29, 2020
1 parent 7dd27ea commit 84f0ef9
Show file tree
Hide file tree
Showing 6 changed files with 104 additions and 91 deletions.
38 changes: 1 addition & 37 deletions xFunc.Maths/Parser.ExpressionFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@

using System.Collections.Immutable;
using System.Diagnostics;
using System.Numerics;
using System.Runtime.CompilerServices;
using xFunc.Maths.Expressions;
using xFunc.Maths.Expressions.Angles;
Expand Down Expand Up @@ -190,24 +189,14 @@ private IExpression CreateFunction(in Token token, ImmutableArray<IExpression> a
return new RightShiftAssign(first, second);
}

private IExpression CreateUnaryAssign(in Token token, Variable first)
{
if (token.Is(IncrementOperator))
return new Inc(first);

Debug.Assert(token.Is(DecrementOperator), "Only '++' and '--' operators are allowed here.");

return new Dec(first);
}

private IExpression CreateBitwiseOperator(
in Token token,
IExpression first,
IExpression second)
{
if (token.Is(ImplicationOperator) || token.Is(ImplKeyword))
return new Implication(first, second);
if (token.Is(TokenKind.EqualityOperator) || token.Is(EqKeyword))
if (token.Is(EqualityOperator) || token.Is(EqKeyword))
return new Equality(first, second);

if (token.Is(NAndKeyword))
Expand Down Expand Up @@ -280,31 +269,6 @@ private IExpression CreateMulDivMod(in Token token, IExpression first, IExpressi
return new Mod(first, second);
}

private IExpression CreateBoolean(in Token token)
{
if (token.Is(TrueKeyword))
return Bool.True;

Debug.Assert(token.Is(FalseKeyword), "Only True and False keywords are allowed here.");

return Bool.False;
}

private IExpression CreateComplexNumber(
in Token magnitude,
in Token phaseSign,
in Token phase)
{
static int GetSign(Token token)
=> token.Is(MinusOperator) ? -1 : 1;

var magnitudeNumber = magnitude.NumberValue;
var phaseNumber = phase.NumberValue * GetSign(phaseSign);
var complex = Complex.FromPolarCoordinates(magnitudeNumber, phaseNumber);

return new ComplexNumber(complex);
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
private Variable CreateVariable(in Token token)
{
Expand Down
91 changes: 51 additions & 40 deletions xFunc.Maths/Parser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,11 @@
using System;
using System.Collections.Immutable;
using System.Globalization;
using System.Numerics;
using xFunc.Maths.Analyzers;
using xFunc.Maths.Expressions;
using xFunc.Maths.Expressions.Angles;
using xFunc.Maths.Expressions.ComplexNumbers;
using xFunc.Maths.Expressions.LogicalAndBitwise;
using xFunc.Maths.Expressions.Matrices;
using xFunc.Maths.Expressions.Programming;
Expand Down Expand Up @@ -92,8 +94,7 @@ public IExpression Parse(string function)

// TODO: to expressions?
private IExpression? ParseStatement(ref TokenReader tokenReader)
=> ParseUnaryAssign(ref tokenReader) ??
ParseBinaryAssign(ref tokenReader) ??
=> ParseBinaryAssign(ref tokenReader) ??
ParseAssign(ref tokenReader) ??
ParseDef(ref tokenReader) ??
ParseUndef(ref tokenReader) ??
Expand All @@ -102,29 +103,6 @@ public IExpression Parse(string function)
ParseWhile(ref tokenReader) ??
ParseExpression(ref tokenReader);

private IExpression? ParseUnaryAssign(ref TokenReader tokenReader)
{
var scope = tokenReader.CreateScope();

var left = ParseVariable(ref tokenReader);
if (left != null)
{
var @operator = tokenReader.GetCurrent(IncrementOperator) ||
tokenReader.GetCurrent(DecrementOperator);

if (@operator.IsNotEmpty())
{
tokenReader.Commit();

return CreateUnaryAssign(@operator, left);
}
}

tokenReader.Rollback(scope);

return null;
}

private IExpression? ParseBinaryAssign(ref TokenReader tokenReader)
{
var scope = tokenReader.CreateScope();
Expand Down Expand Up @@ -717,24 +695,48 @@ public IExpression Parse(string function)
}

private IExpression? ParseRightUnary(ref TokenReader tokenReader)
=> ParseFactorial(ref tokenReader) ??
ParseIncDec(ref tokenReader) ??
ParseOperand(ref tokenReader);

private IExpression? ParseFactorial(ref TokenReader tokenReader)
{
var scope = tokenReader.CreateScope();

var number = ParseNumber(ref tokenReader);
if (number != null)
if (number != null && tokenReader.Check(FactorialOperator))
{
var @operator = tokenReader.GetCurrent(FactorialOperator);
if (@operator.IsNotEmpty())
{
tokenReader.Commit();
tokenReader.Commit();

return new Fact(number);
}
return new Fact(number);
}

tokenReader.Rollback(scope);

return ParseOperand(ref tokenReader);
return null;
}

private IExpression? ParseIncDec(ref TokenReader tokenReader)
{
var scope = tokenReader.CreateScope();

var variable = ParseVariable(ref tokenReader);
if (variable != null)
{
tokenReader.Commit();

if (tokenReader.Check(IncrementOperator))
return new Inc(variable);

if (tokenReader.Check(DecrementOperator))
return new Dec(variable);

return variable;
}

tokenReader.Rollback(scope);

return null;
}

private IExpression? ParseOperand(ref TokenReader tokenReader)
Expand Down Expand Up @@ -844,7 +846,12 @@ private ImmutableArray<IExpression> ParseParameterList(ref TokenReader tokenRead

tokenReader.Commit();

return CreateComplexNumber(magnitude, phaseSign, phase);
var magnitudeNumber = magnitude.NumberValue;
var sign = phaseSign.Is(MinusOperator) ? -1 : 1;
var phaseNumber = phase.NumberValue * sign;
var complex = Complex.FromPolarCoordinates(magnitudeNumber, phaseNumber);

return new ComplexNumber(complex);
}
}

Expand All @@ -856,21 +863,25 @@ private ImmutableArray<IExpression> ParseParameterList(ref TokenReader tokenRead
private Variable? ParseVariable(ref TokenReader tokenReader)
{
var variable = tokenReader.GetCurrent(Id);
if (variable.IsEmpty())

// usually we use 'scope' in such cases, but here we can ignore it,
// because parsing of variable is always 'scoped'
// if it is not true anymore, then use 'scope'
if (variable.IsEmpty() || tokenReader.Check(OpenParenthesisSymbol))
return null;

return CreateVariable(variable);
}

private IExpression? ParseBoolean(ref TokenReader tokenReader)
{
var boolean = tokenReader.GetCurrent(TrueKeyword) ||
tokenReader.GetCurrent(FalseKeyword);
if (tokenReader.Check(TrueKeyword))
return Bool.True;

if (boolean.IsEmpty())
return null;
if (tokenReader.Check(FalseKeyword))
return Bool.False;

return CreateBoolean(boolean);
return null;
}

private Vector? ParseVector(ref TokenReader tokenReader)
Expand Down
11 changes: 11 additions & 0 deletions xFunc.Tests/Expressions/Programming/DecTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,17 @@ public void DecCalcTest()
Assert.Equal(9.0, parameters["x"]);
}

[Fact]
public void DecAsExpExecuteTest()
{
var parameters = new ParameterCollection { new Parameter("x", 10) };
var inc = new Add(Number.One, new Dec(Variable.X));
var result = (double)inc.Execute(parameters);

Assert.Equal(10.0, result);
Assert.Equal(9.0, parameters["x"]);
}

[Fact]
public void DecNullParameters()
{
Expand Down
11 changes: 11 additions & 0 deletions xFunc.Tests/Expressions/Programming/IncTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,17 @@ public void IncCalcTest()
Assert.Equal(11.0, parameters["x"]);
}

[Fact]
public void IncAsExpExecuteTest()
{
var parameters = new ParameterCollection { new Parameter("x", 10) };
var inc = new Add(Number.One, new Inc(Variable.X));
var result = (double)inc.Execute(parameters);

Assert.Equal(12.0, result);
Assert.Equal(11.0, parameters["x"]);
}

[Fact]
public void IncNullParameters()
{
Expand Down
30 changes: 30 additions & 0 deletions xFunc.Tests/ParserTests/AssignTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -173,5 +173,35 @@ public void RightShiftAssignTest()

ParseTest("x >>= 10", expected);
}

[Fact]
public void IncTest()
=> ParseTest("x++", new Inc(Variable.X));

[Fact]
public void IncAsExpression()
{
var expected = new Add(Number.One, new Inc(Variable.X));

ParseTest("1 + x++", expected);
}

[Theory]
[InlineData("x--")]
[InlineData("x−−")]
public void DecTest(string function)
{
var expected = new Dec(Variable.X);

ParseTest(function, expected);
}

[Fact]
public void DecAsExpression()
{
var expected = new Add(Number.One, new Dec(Variable.X));

ParseTest("1 + x--", expected);
}
}
}
14 changes: 0 additions & 14 deletions xFunc.Tests/ParserTests/ParserTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -188,20 +188,6 @@ public void MatrixWithDiffVectorSizeTest()
public void TooMuchParamsTest()
=> ParseErrorTest("sin(x, 3)");

[Fact]
public void IncTest()
=> ParseTest("x++", new Inc(Variable.X));

[Theory]
[InlineData("x--")]
[InlineData("x−−")]
public void DecTest(string function)
{
var expected = new Dec(Variable.X);

ParseTest(function, expected);
}

[Fact]
public void ModuloTest()
{
Expand Down

0 comments on commit 84f0ef9

Please sign in to comment.