Skip to content

Commit

Permalink
#304 - Parse binary assign as expression
Browse files Browse the repository at this point in the history
  • Loading branch information
sys27 committed Oct 1, 2020
1 parent 2b0caa6 commit 47d4787
Show file tree
Hide file tree
Showing 9 changed files with 217 additions and 68 deletions.
14 changes: 9 additions & 5 deletions xFunc Grammar.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,6 @@ statement = unaryAssign
/ while
/ exp

unaryAssign = variable ('++' / '--')
binaryAssign = variable ('+=' / '-=' / '*=' / '/=' / '<<=' / '>>=') exp

assignmentKey = functionDeclaration / variable
assign = assignmentKey ':=' exp
def = ('def' / 'define') '(' assignmentKey ',' exp ')'
Expand All @@ -22,8 +19,10 @@ if = 'if' '(' conditional ',' exp (',' exp)* ')'
for = 'for' '(' statement ',' exp ',' conditional ',' statement ')'
while = 'while' '(' exp ',' conditional ')'

exp = ternary
exp = binaryAssign
/ ternary

binaryAssign = variable ('+=' / '-=' / '*=' / '/=' / '<<=' / '>>=') exp
ternary = conditional ('?' exp ':' exp)*

conditional = bitwise (('&&' / '||') bitwise)*
Expand All @@ -36,7 +35,12 @@ mulImplicit = mulImplicitLeftUnary / leftUnary
mulImplicitLeftUnary = '-'* number rightUnary
leftUnary = ('~' / '-')* exponentiation
exponentiation = rightUnary ('^' exponentiation)*
rightUnary = (number '!') / operand
rightUnary = incDec
/ factorial
/ operand

incDec = variable ('++' / '--')
factorial = (number '!')

operand = complexnumber /
number /
Expand Down
71 changes: 36 additions & 35 deletions xFunc.Maths/Parser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -103,40 +103,6 @@ public IExpression Parse(string function)
ParseWhile(ref tokenReader) ??
ParseExpression(ref tokenReader);

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

var left = ParseVariable(ref tokenReader);
if (left == null)
{
tokenReader.Rollback(scope);

return null;
}

var @operator = tokenReader.GetCurrent(MulAssignOperator) ||
tokenReader.GetCurrent(DivAssignOperator) ||
tokenReader.GetCurrent(AddAssignOperator) ||
tokenReader.GetCurrent(SubAssignOperator) ||
tokenReader.GetCurrent(LeftShiftAssignOperator) ||
tokenReader.GetCurrent(RightShiftAssignOperator);

if (@operator.IsNotEmpty())
{
var right = ParseExpression(ref tokenReader) ??
MissingSecondOperand(@operator.Kind);

tokenReader.Commit();

return CreateBinaryAssign(@operator, left, right);
}

tokenReader.Rollback(scope);

return null;
}

private IExpression? AssignmentKey(ref TokenReader tokenReader)
=> ParseFunctionDeclaration(ref tokenReader) ??
ParseVariable(ref tokenReader);
Expand Down Expand Up @@ -345,7 +311,42 @@ public IExpression Parse(string function)
}

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

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

var variable = ParseVariable(ref tokenReader);
if (variable == null)
{
tokenReader.Rollback(scope);

return null;
}

var @operator = tokenReader.GetCurrent(MulAssignOperator) ||
tokenReader.GetCurrent(DivAssignOperator) ||
tokenReader.GetCurrent(AddAssignOperator) ||
tokenReader.GetCurrent(SubAssignOperator) ||
tokenReader.GetCurrent(LeftShiftAssignOperator) ||
tokenReader.GetCurrent(RightShiftAssignOperator);

if (@operator.IsNotEmpty())
{
var exp = ParseExpression(ref tokenReader) ??
MissingSecondOperand(@operator.Kind);

tokenReader.Commit();

return CreateBinaryAssign(@operator, variable, exp);
}

tokenReader.Rollback(scope);

return null;
}

private IExpression? Ternary(ref TokenReader tokenReader)
{
Expand Down
11 changes: 11 additions & 0 deletions xFunc.Tests/Expressions/Programming/AddAssignTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,17 @@ public void AddAssignCalc()
Assert.Equal(expected, parameters["x"]);
}

[Fact]
public void AddAssignAsExpressionTest()
{
var parameters = new ParameterCollection { new Parameter("x", 10) };
var add = new Add(Number.One, new AddAssign(Variable.X, Number.Two));
var result = add.Execute(parameters);

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

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

[Fact]
public void DivAssignAsExpressionTest()
{
var parameters = new ParameterCollection { new Parameter("x", 10) };
var add = new Div(new AddAssign(Variable.X, Number.Two), Number.Two);
var result = add.Execute(parameters);

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

[Fact]
public void DivNullParameters()
{
Expand Down
14 changes: 14 additions & 0 deletions xFunc.Tests/Expressions/Programming/LeftShiftAssignTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,20 @@ public void ExecuteTest()
Assert.Equal(expected, actual);
}

[Fact]
public void ExecuteAsExpressionTest()
{
var exp = new Add(Number.One, new LeftShiftAssign(Variable.X, new Number(10)));
var parameters = new ParameterCollection
{
new Parameter("x", 1.0)
};
var actual = exp.Execute(parameters);

Assert.Equal(1025.0, actual);
Assert.Equal(1024.0, parameters["x"]);
}

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

[Fact]
public void MulAssignAsExpressionTest()
{
var parameters = new ParameterCollection { new Parameter("x", 10) };
var add = new Mul(Number.Two, new AddAssign(Variable.X, Number.Two));
var result = add.Execute(parameters);

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

[Fact]
public void MulNullParameters()
{
Expand Down
14 changes: 14 additions & 0 deletions xFunc.Tests/Expressions/Programming/RightShiftAssignTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,20 @@ public void ExecuteTest()
Assert.Equal(expected, actual);
}

[Fact]
public void ExecuteAsExpressionTest()
{
var exp = new Add(Number.One, new RightShiftAssign(Variable.X, new Number(9)));
var parameters = new ParameterCollection
{
new Parameter("x", 512.0)
};
var actual = exp.Execute(parameters);

Assert.Equal(2.0, actual);
Assert.Equal(1.0, parameters["x"]);
}

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

[Fact]
public void SubAssignAsExpressionTest()
{
var parameters = new ParameterCollection { new Parameter("x", 10) };
var add = new Sub(Number.One, new AddAssign(Variable.X, Number.Two));
var result = add.Execute(parameters);

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

[Fact]
public void SubNullParameters()
{
Expand Down

0 comments on commit 47d4787

Please sign in to comment.