Skip to content

Commit 5263345

Browse files
committed
Add expressions API
1 parent d0f2051 commit 5263345

8 files changed

Lines changed: 412 additions & 0 deletions

File tree

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
namespace StringMath.Expressions.Tests
2+
{
3+
public class ExpressionsTests
4+
{
5+
[Theory]
6+
[InlineData("5 * (3 + 2)", "5 * 3 + 5 * 2")]
7+
[InlineData("5 * (3 - 2)", "5 * 3 - 5 * 2")]
8+
[InlineData("{a} * (3 + {b})", "{a} * 3 + {a} * {b}")]
9+
[InlineData("{a} * (3 - {b})", "{a} * 3 - {a} * {b}")]
10+
public void Expand(string input, string expected)
11+
{
12+
var actual = input.Expand();
13+
14+
Assert.Equal(expected, actual.Text);
15+
}
16+
17+
[Theory]
18+
[InlineData("5^2", "25")]
19+
[InlineData("(5 - 2) * {a}", "3 * {a}")]
20+
[InlineData("(-5 + 2) * {a}", "-3 * {a}")]
21+
[InlineData("-(-5 + 2) * {a}", "3 * {a}")]
22+
[InlineData("-(-5 + 1)", "4")]
23+
[InlineData("-(-5 + -1)", "6")]
24+
[InlineData("-{a} + 2", "-{a} + 2")]
25+
public void Simplify(string input, string expected)
26+
{
27+
var actual = input.Simplify();
28+
29+
Assert.Equal(expected, actual.Text);
30+
}
31+
}
32+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<TargetFramework>net6.0</TargetFramework>
5+
<ImplicitUsings>enable</ImplicitUsings>
6+
<Nullable>enable</Nullable>
7+
8+
<IsPackable>false</IsPackable>
9+
</PropertyGroup>
10+
11+
<ItemGroup>
12+
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.1.0" />
13+
<PackageReference Include="xunit" Version="2.4.1" />
14+
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3">
15+
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
16+
<PrivateAssets>all</PrivateAssets>
17+
</PackageReference>
18+
<PackageReference Include="coverlet.collector" Version="3.1.2">
19+
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
20+
<PrivateAssets>all</PrivateAssets>
21+
</PackageReference>
22+
</ItemGroup>
23+
24+
<ItemGroup>
25+
<ProjectReference Include="..\StringMath.Expressions\StringMath.Expressions.csproj" />
26+
<ProjectReference Include="..\StringMath\StringMath.csproj" />
27+
</ItemGroup>
28+
29+
</Project>
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
global using Xunit;

StringMath.Expressions/Expr.cs

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
namespace StringMath.Expressions;
2+
3+
public record Expr
4+
{
5+
public static Mul operator *(Expr left, Expr right) => new(left, right);
6+
public static Div operator /(Expr left, Expr right) => new(left, right);
7+
public static Sum operator +(Expr left, Expr right) => new(left, right);
8+
public static Diff operator -(Expr left, Expr right) => new(left, right);
9+
public static Pow operator ^(Expr left, Expr right) => new(left, right);
10+
public static Mod operator %(Expr left, Expr right) => new(left, right);
11+
public static Neg operator -(Expr operand) => new(operand);
12+
13+
public static implicit operator Expr(double value) => new Number(value);
14+
}
15+
16+
public record Variable(string Name) : Expr;
17+
public record Number(double Value) : Expr
18+
{
19+
public static implicit operator Number(double val) => new(val);
20+
public static implicit operator double(Number num) => num.Value;
21+
}
22+
public record Binary(Expr Left, string Op, Expr Right) : Expr;
23+
public record Unary(Expr Value, string Op) : Expr;
24+
25+
public record Neg(Expr Value) : Unary(Value, "-");
26+
public record Factorial(Expr Value) : Unary(Value, "!");
27+
public record Sin(Expr Value) : Unary(Value, "sin");
28+
public record Cos(Expr Value) : Unary(Value, "cos");
29+
public record Abs(Expr Value) : Unary(Value, "abs");
30+
public record Sqrt(Expr Value) : Unary(Value, "sqrt");
31+
public record Tan(Expr Value) : Unary(Value, "tan");
32+
public record Atan(Expr Value) : Unary(Value, "atan");
33+
public record Exp(Expr Value) : Unary(Value, "exp");
34+
35+
public record Sum(Expr Left, Expr Right) : Binary(Left, "+", Right);
36+
public record Diff(Expr Left, Expr Right) : Binary(Left, "-", Right);
37+
public record Mul(Expr Left, Expr Right) : Binary(Left, "*", Right);
38+
public record Div(Expr Left, Expr Right) : Binary(Left, "/", Right);
39+
public record Pow(Expr Left, Expr Right) : Binary(Left, "^", Right);
40+
public record Mod(Expr Left, Expr Right) : Binary(Left, "%", Right);
41+
public record Log(Expr Left, Expr Right) : Binary(Left, "log", Right);
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
namespace StringMath.Expressions;
2+
3+
public static class Factory
4+
{
5+
public delegate Expr BinaryExprFactory(Expr left, string op, Expr right);
6+
public delegate Expr UnaryExprFactory(string op, Expr operand);
7+
8+
public static BinaryExprFactory BinaryExpr = (left, op, right) => op switch
9+
{
10+
"+" => new Sum(left, right),
11+
"-" => new Diff(left, right),
12+
"/" => new Div(left, right),
13+
"*" => new Mul(left, right),
14+
"^" => new Pow(left, right),
15+
"%" => new Mod(left, right),
16+
"log" => new Log(left, right),
17+
_ => new Binary(left, op, right),
18+
};
19+
20+
public static UnaryExprFactory UnaryExpr = (op, operand) => op switch
21+
{
22+
"-" => new Neg(operand),
23+
"!" => new Factorial(operand),
24+
"sin" => new Sin(operand),
25+
"cos" => new Cos(operand),
26+
"abs" => new Abs(operand),
27+
"tan" => new Tan(operand),
28+
"atan" => new Atan(operand),
29+
"sqrt" => new Sqrt(operand),
30+
"exp" => new Exp(operand),
31+
_ => new Unary(operand, op)
32+
};
33+
}
34+
35+
internal static partial class ExprConversion
36+
{
37+
public static Expr Convert(IExpression expression)
38+
{
39+
Expr result = expression switch
40+
{
41+
BinaryExpression binaryExpr => ConvertBinaryExpr(binaryExpr),
42+
ConstantExpression constantExpr => ConvertConstantExpr(constantExpr),
43+
UnaryExpression unaryExpr => ConvertUnaryExpr(unaryExpr),
44+
VariableExpression variableExpr => ConvertVariableExpr(variableExpr),
45+
_ => throw new NotImplementedException($"'{expression.Type}' Convertor is not implemented.")
46+
};
47+
48+
return result;
49+
}
50+
51+
public static Expr ConvertVariableExpr(VariableExpression variableExpr) => new Variable(variableExpr.Name);
52+
53+
public static Expr ConvertConstantExpr(ConstantExpression constantExpr) => new Number(constantExpr.Value);
54+
55+
public static Expr ConvertBinaryExpr(BinaryExpression binaryExpr)
56+
{
57+
Expr left = Convert(binaryExpr.Left);
58+
Expr right = Convert(binaryExpr.Right);
59+
60+
return Factory.BinaryExpr(left, binaryExpr.OperatorName, right);
61+
}
62+
63+
public static Expr ConvertUnaryExpr(UnaryExpression unaryExpr)
64+
{
65+
Expr operand = Convert(unaryExpr.Operand);
66+
return Factory.UnaryExpr(unaryExpr.OperatorName, operand);
67+
}
68+
}
69+
70+
internal partial class ExprConversion
71+
{
72+
public static IExpression Convert(Expr expression)
73+
{
74+
IExpression result = expression switch
75+
{
76+
Binary binaryExpr => ConvertBinaryExpr(binaryExpr),
77+
Number constantExpr => ConvertConstantExpr(constantExpr),
78+
Unary unaryExpr => ConvertUnaryExpr(unaryExpr),
79+
Variable variableExpr => ConvertVariableExpr(variableExpr),
80+
_ => throw new NotImplementedException($"'{expression?.GetType().Name}' Convertor is not implemented.")
81+
};
82+
83+
return result;
84+
}
85+
86+
public static IExpression ConvertVariableExpr(Variable variableExpr) => new VariableExpression(variableExpr.Name);
87+
88+
public static IExpression ConvertConstantExpr(Number constantExpr) => new ConstantExpression(constantExpr.Value);
89+
90+
public static IExpression ConvertBinaryExpr(Binary binaryExpr) => new BinaryExpression(Convert(binaryExpr.Left), binaryExpr.Op, Convert(binaryExpr.Right));
91+
92+
public static IExpression ConvertUnaryExpr(Unary unaryExpr) => new UnaryExpression(unaryExpr.Op, Convert(unaryExpr.Value));
93+
}

0 commit comments

Comments
 (0)