Skip to content

Commit df5b488

Browse files
added some expression magic
1 parent b093448 commit df5b488

23 files changed

+314
-167
lines changed

Demo/Program.cs

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,20 +14,29 @@ public static void Main(string[] args)
1414

1515
SymbolManager symbolManager = new SymbolManager();
1616
symbolManager.SetTrigonometrySymbols();
17+
symbolManager.SetEvalSymbol();
1718

1819
Console.WriteLine("Enter {0} to quit calculator.", exitCommand);
1920

2021
while (ReadNextLine())
2122
{
2223
try
2324
{
24-
ExpressionTree expressionTree = mathParser.Parse(currentLine);
25+
Expression expression = mathParser.Parse(currentLine);
2526

26-
string detail = expressionTree.ToDebug();
27-
Value result = expressionTree.Evaluate(symbolManager);
27+
string detail = expression.ToDebug();
28+
Value result = expression.Evaluate(symbolManager);
2829

29-
Console.WriteLine("{0} = {1}", detail, result);
30-
expressionTree.Assign(symbolManager);
30+
if (result.IsExpression)
31+
{
32+
Console.WriteLine("{0} = `{1}`", detail, result);
33+
}
34+
else
35+
{
36+
Console.WriteLine("{0} = {1}", detail, result);
37+
}
38+
39+
expression.ExecuteAssignments(symbolManager);
3140
}
3241
catch (Exception exception)
3342
{

ExpressionTest/TestFunctions.cs

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,23 +10,27 @@ public class TestFunctions
1010
[Test]
1111
public void TestFuncAssignment1()
1212
{
13+
SymbolManager symbolManager = new SymbolManager();
14+
1315
MathParser.MathParser parser = new MathParser.MathParser();
14-
ExpressionTree tree = parser.Parse("f(x)=3");
15-
//tree.Assign();
16+
Expression expression = parser.Parse("f(x)=3");
17+
expression.ExecuteAssignments(symbolManager);
1618

17-
//double a = parser.Parse("f(2)").Evaluate();
18-
//Assert.AreEqual(3, a);
19+
double a = parser.Parse("f(2)").Evaluate(symbolManager).ToDouble();
20+
Assert.AreEqual(3, a);
1921
}
2022

2123
[Test]
2224
public void TestFuncAssignment2()
2325
{
26+
SymbolManager symbolManager = new SymbolManager();
27+
2428
MathParser.MathParser parser = new MathParser.MathParser();
25-
ExpressionTree tree = parser.Parse("f(x)=x*x");
26-
//tree.Assign();
29+
Expression expression = parser.Parse("f(x)=x*x");
30+
expression.ExecuteAssignments(symbolManager);
2731

28-
//double a = parser.Parse("f(5)").Evaluate();
29-
//Assert.AreEqual(25, a);
32+
double a = parser.Parse("f(5)").Evaluate(symbolManager).ToDouble();
33+
Assert.AreEqual(25, a);
3034
}
3135
}
3236
}

ExpressionTest/TestValueClass.cs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,17 +11,17 @@ public void TestInteger()
1111
{
1212
Value integer = Value.Integer(16);
1313
Assert.IsTrue(integer.IsInteger);
14-
Assert.IsFalse(integer.IsFloatingPointNumber);
14+
Assert.IsFalse(integer.IsDecimal);
1515
Assert.IsFalse(integer.IsBoolean);
1616
Assert.IsFalse(integer.IsFunction);
1717
}
1818

1919
[Test]
2020
public void TestFloatingPointNumber()
2121
{
22-
Value floatingPointNumber = Value.FloatingPointNumber(-2.3);
22+
Value floatingPointNumber = Value.Decimal(-2.3);
2323
Assert.IsFalse(floatingPointNumber.IsInteger);
24-
Assert.IsTrue(floatingPointNumber.IsFloatingPointNumber);
24+
Assert.IsTrue(floatingPointNumber.IsDecimal);
2525
Assert.IsFalse(floatingPointNumber.IsBoolean);
2626
Assert.IsFalse(floatingPointNumber.IsFunction);
2727
}
@@ -31,7 +31,7 @@ public void TestBoolean()
3131
{
3232
Value boolean = Value.Boolean(true);
3333
Assert.IsFalse(boolean.IsInteger);
34-
Assert.IsFalse(boolean.IsFloatingPointNumber);
34+
Assert.IsFalse(boolean.IsDecimal);
3535
Assert.IsTrue(boolean.IsBoolean);
3636
Assert.IsFalse(boolean.IsFunction);
3737
}
@@ -41,7 +41,7 @@ public void TestFunction()
4141
{
4242
Value function = Value.Function(someCalculationFunction);
4343
Assert.IsFalse(function.IsInteger);
44-
Assert.IsFalse(function.IsFloatingPointNumber);
44+
Assert.IsFalse(function.IsDecimal);
4545
Assert.IsFalse(function.IsBoolean);
4646
Assert.IsTrue(function.IsFunction);
4747
}

ExpressionTest/TestVariables.cs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,13 @@ public class TestVariables
1010
[Test]
1111
public void TestAssignment()
1212
{
13+
SymbolManager symbolManager = new SymbolManager();
14+
1315
MathParser.MathParser parser = new MathParser.MathParser();
14-
ExpressionTree tree = parser.Parse("a = 3");
15-
//tree.Assign();
16+
Expression expression = parser.Parse("a = 3");
17+
expression.ExecuteAssignments(symbolManager);
1618

17-
double a = parser.Parse("a=3").Evaluate().ToDouble();
19+
double a = parser.Parse("a").Evaluate(symbolManager).ToDouble();
1820
Assert.AreEqual(3, a);
1921
}
2022

ExpressionTest/TokenizerTest.cs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -43,17 +43,17 @@ public void TestEveryTokenType()
4343
public void TestNumberToken()
4444
{
4545
AssertTokensMatch("23123", Token(TokenType.Integer, "23123", 0), Token(TokenType.EndOfFile, "", 5));
46-
AssertTokensMatch(".23", Token(TokenType.FloatingPointNumber, ".23", 0), Token(TokenType.EndOfFile, "", 3));
47-
AssertTokensMatch("13.3", Token(TokenType.FloatingPointNumber, "13.3", 0), Token(TokenType.EndOfFile, "", 4));
46+
AssertTokensMatch(".23", Token(TokenType.Decimal, ".23", 0), Token(TokenType.EndOfFile, "", 3));
47+
AssertTokensMatch("13.3", Token(TokenType.Decimal, "13.3", 0), Token(TokenType.EndOfFile, "", 4));
4848
AssertTokensMatch("27.", Token(TokenType.Unknown, "27.", 0), Token(TokenType.EndOfFile, "", 3));
49-
AssertTokensMatch("1e10", Token(TokenType.FloatingPointNumber, "1e10", 0), Token(TokenType.EndOfFile, "", 4));
49+
AssertTokensMatch("1e10", Token(TokenType.Decimal, "1e10", 0), Token(TokenType.EndOfFile, "", 4));
5050
AssertTokensMatch("1.e10", Token(TokenType.Unknown, "1.e10", 0), Token(TokenType.EndOfFile, "", 5));
51-
AssertTokensMatch("1.7e3", Token(TokenType.FloatingPointNumber, "1.7e3", 0), Token(TokenType.EndOfFile, "", 5));
52-
AssertTokensMatch("1.22e+4", Token(TokenType.FloatingPointNumber, "1.22e+4", 0), Token(TokenType.EndOfFile, "", 7));
53-
AssertTokensMatch("1.22e-34", Token(TokenType.FloatingPointNumber, "1.22e-34", 0), Token(TokenType.EndOfFile, "", 8));
51+
AssertTokensMatch("1.7e3", Token(TokenType.Decimal, "1.7e3", 0), Token(TokenType.EndOfFile, "", 5));
52+
AssertTokensMatch("1.22e+4", Token(TokenType.Decimal, "1.22e+4", 0), Token(TokenType.EndOfFile, "", 7));
53+
AssertTokensMatch("1.22e-34", Token(TokenType.Decimal, "1.22e-34", 0), Token(TokenType.EndOfFile, "", 8));
5454
AssertTokensMatch("-3.4",
5555
Token(TokenType.Minus, "-", 0),
56-
Token(TokenType.FloatingPointNumber, "3.4", 1),
56+
Token(TokenType.Decimal, "3.4", 1),
5757
Token(TokenType.EndOfFile, "", 4));
5858
}
5959

shunting_yard/MathParser.csproj

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,6 @@
4747
<Compile Include="src\expressions\VariableAssignmentExpression.cs" />
4848
<Compile Include="src\visitors\IExpressionVisitor.cs" />
4949
<Compile Include="src\expressions\BinaryExpressionType.cs" />
50-
<Compile Include="src\visitors\EvaluationVisitor.cs" />
51-
<Compile Include="src\visitors\ExpressionTree.cs" />
5250
<Compile Include="src\expressions\PrefixExpressionType.cs" />
5351
<Compile Include="src\expressions\PrefixExpression.cs" />
5452
<Compile Include="src\expressions\PostfixExpression.cs" />
@@ -88,10 +86,15 @@
8886
<Compile Include="src\symbol_manager\SymbolManager.cs" />
8987
<Compile Include="src\symbol_manager\ISymbolManager.cs" />
9088
<Compile Include="src\symbol_manager\TrigonometrySymbols.cs" />
91-
<Compile Include="src\expressions\Value.cs" />
9289
<Compile Include="src\tokenizer\Identifier.cs" />
9390
<Compile Include="src\parser\parselets\FixValueParselet.cs" />
9491
<Compile Include="src\parser\parselets\FloatingPointNumberParselet %28copy%29.cs" />
92+
<Compile Include="src\expressions\SymbolicExpression.cs" />
93+
<Compile Include="src\symbol_manager\Expression.cs" />
94+
<Compile Include="src\evaluation\EvaluationVisitor.cs" />
95+
<Compile Include="src\evaluation\Value.cs" />
96+
<Compile Include="src\evaluation\Add.cs" />
97+
<Compile Include="src\symbol_manager\EvaluateSymbols.cs" />
9598
</ItemGroup>
9699
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
97100
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
@@ -110,5 +113,6 @@
110113
<Folder Include="src\parser\exceptions\" />
111114
<Folder Include="src\parser\parselets\" />
112115
<Folder Include="src\symbol_manager\" />
116+
<Folder Include="src\evaluation\" />
113117
</ItemGroup>
114118
</Project>
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
namespace MathParser
2+
{
3+
public partial class Value
4+
{
5+
public static Value Add(Value valueA, Value valueB)
6+
{
7+
if (valueA.IsInteger && valueB.IsInteger)
8+
{
9+
long a = valueA.ToInt64();
10+
long b = valueB.ToInt64();
11+
return Integer(a + b);
12+
}
13+
14+
bool isNumberA = valueA.IsDecimal || valueA.IsInteger;
15+
bool isNumberB = valueB.IsDecimal || valueB.IsInteger;
16+
17+
if (isNumberA && isNumberB)
18+
{
19+
double a = valueA.ToDouble();
20+
double b = valueB.ToDouble();
21+
return Decimal(a + b);
22+
}
23+
24+
if (valueA.IsExpression || valueB.IsExpression)
25+
{
26+
IExpression a = new ValueExpression(valueA);
27+
IExpression b = new ValueExpression(valueB);
28+
IExpression result = new BinaryExpression(BinaryExpressionType.Addition, a, b);
29+
return Expression(new Expression(result));
30+
}
31+
32+
string message = string.Format("Incompatible types of operands {0} and {1} for binary operation {2}.",
33+
valueA.ValueType, valueB.ValueType, BinaryExpressionType.Addition);
34+
throw new EvaluationException(message);
35+
}
36+
}
37+
}

shunting_yard/src/visitors/EvaluationVisitor.cs renamed to shunting_yard/src/evaluation/EvaluationVisitor.cs

Lines changed: 41 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,9 @@ class EvaluationVisitor : IExpressionVisitor
1111

1212
public Traversal Traversal { get { return Traversal.None; } }
1313

14-
public EvaluationVisitor(ISymbolManager symbolProvider)
14+
public EvaluationVisitor(ISymbolManager symbolManager)
1515
{
16-
_symbolManager = symbolProvider;
16+
_symbolManager = symbolManager;
1717
_evaluationStack = new Stack<Value>();
1818
}
1919

@@ -37,8 +37,16 @@ public void Visit(BinaryExpression binaryExpression)
3737

3838
Value rightOperand = _evaluationStack.Pop();
3939
Value leftOperand = _evaluationStack.Pop();
40-
bool isNumberLeft = leftOperand.IsFloatingPointNumber || leftOperand.IsInteger;
41-
bool isNumberRight = rightOperand.IsFloatingPointNumber || rightOperand.IsInteger;
40+
bool isNumberLeft = leftOperand.IsDecimal || leftOperand.IsInteger;
41+
bool isNumberRight = rightOperand.IsDecimal || rightOperand.IsInteger;
42+
43+
switch (binaryExpression.BinaryExpressionType)
44+
{
45+
case BinaryExpressionType.Addition:
46+
Value result = Value.Add(leftOperand, rightOperand);
47+
_evaluationStack.Push(result);
48+
return;
49+
}
4250

4351
if (isNumberLeft && isNumberRight)
4452
{
@@ -48,23 +56,20 @@ public void Visit(BinaryExpression binaryExpression)
4856

4957
switch (binaryExpression.BinaryExpressionType)
5058
{
51-
case BinaryExpressionType.Addition:
52-
result = Value.FloatingPointNumber(leftValue + rightValue);
53-
break;
5459
case BinaryExpressionType.Substraction:
55-
result = Value.FloatingPointNumber(leftValue - rightValue);
60+
result = Value.Decimal(leftValue - rightValue);
5661
break;
5762
case BinaryExpressionType.Multiplication:
58-
result = Value.FloatingPointNumber(leftValue * rightValue);
63+
result = Value.Decimal(leftValue * rightValue);
5964
break;
6065
case BinaryExpressionType.Division:
61-
result = Value.FloatingPointNumber(leftValue / rightValue);
66+
result = Value.Decimal(leftValue / rightValue);
6267
break;
6368
case BinaryExpressionType.Power:
64-
result = Value.FloatingPointNumber(Math.Pow(leftValue, rightValue));
69+
result = Value.Decimal(Math.Pow(leftValue, rightValue));
6570
break;
6671
case BinaryExpressionType.Modulo:
67-
result = Value.FloatingPointNumber(leftValue % rightValue);
72+
result = Value.Decimal(leftValue % rightValue);
6873
break;
6974
case BinaryExpressionType.Equal:
7075
result = Value.Boolean(leftValue == rightValue);
@@ -107,7 +112,7 @@ public void Visit(PrefixExpression prefixExpression)
107112

108113
Value operand = _evaluationStack.Pop();
109114

110-
if (operand.IsInteger || operand.IsFloatingPointNumber)
115+
if (operand.IsInteger || operand.IsDecimal)
111116
{
112117
double value = operand.ToDouble();
113118
double result;
@@ -122,7 +127,7 @@ public void Visit(PrefixExpression prefixExpression)
122127
throw new EvaluationException(message);
123128
}
124129

125-
_evaluationStack.Push(Value.FloatingPointNumber(result));
130+
_evaluationStack.Push(Value.Decimal(result));
126131
}
127132
else
128133
{
@@ -132,9 +137,16 @@ public void Visit(PrefixExpression prefixExpression)
132137
}
133138
}
134139

135-
public void Visit(ValueExpression numberExpression)
140+
public void Visit(ValueExpression valueExpression)
136141
{
137-
_evaluationStack.Push(numberExpression.Value);
142+
if (valueExpression.Value.IsExpression)
143+
{
144+
valueExpression.Value.ToExpression().Expr.Accept(this);
145+
}
146+
else
147+
{
148+
_evaluationStack.Push(valueExpression.Value);
149+
}
138150
}
139151

140152
public void Visit(CallExpression functionExpression)
@@ -197,13 +209,23 @@ public void Visit(TernaryExpression ternaryExpression)
197209

198210
public virtual void Visit(VariableExpression variableExpression)
199211
{
200-
if (_symbolManager.IsSet(variableExpression.Identifier))
212+
if (_symbolManager != null && _symbolManager.IsSet(variableExpression.Identifier))
201213
{
202-
_evaluationStack.Push(_symbolManager.Get(variableExpression.Identifier));
214+
// TODO decide whether this is good or not , do we want to evaluate like that?!
215+
Value value = _symbolManager.Get(variableExpression.Identifier);
216+
217+
if (value.IsExpression)
218+
{
219+
value.ToExpression().Expr.Accept(this);
220+
}
221+
else
222+
{
223+
_evaluationStack.Push(value);
224+
}
203225
}
204226
else
205227
{
206-
throw new EvaluationException("Unknown variable " + variableExpression.Identifier + ".");
228+
_evaluationStack.Push(Value.Expression(new Expression(variableExpression)));
207229
}
208230
}
209231

0 commit comments

Comments
 (0)