Skip to content

Commit 6d5dd04

Browse files
committed
Correction Of #33 and tests
1 parent 1ade392 commit 6d5dd04

File tree

2 files changed

+71
-38
lines changed

2 files changed

+71
-38
lines changed

CodingSeb.ExpressionEvaluator.Tests/ExpressionEvaluatorTests.cs

Lines changed: 41 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1478,28 +1478,52 @@ public static IEnumerable<TestCaseData> TestCasesEvaluateWithSpecificEvaluator
14781478
#region Force Integer numbers default type
14791479

14801480
yield return new TestCaseData(new ExpressionEvaluator()
1481-
, "(130-120)/(2*250)")
1482-
.Returns(0)
1483-
.SetCategory("Options")
1484-
.SetCategory("Integer Numbers default types");
1481+
, "(130-120)/(2*250)")
1482+
.Returns(0)
1483+
.SetCategory("Options")
1484+
.SetCategory("Integer Numbers default types");
14851485

1486-
yield return new TestCaseData(new ExpressionEvaluator
1487-
{
1488-
OptionForceIntegerNumbersEvaluationsAsDoubleByDefault = false
1489-
}
1490-
, "(130-120)/(2*250)")
1491-
.Returns(0)
1492-
.SetCategory("Options")
1493-
.SetCategory("Integer Numbers default types");
14941486

14951487
yield return new TestCaseData(new ExpressionEvaluator
1488+
{
1489+
OptionForceIntegerNumbersEvaluationsAsDoubleByDefault = false
1490+
}
1491+
, "(130-120)/(2*250)")
1492+
.Returns(0)
1493+
.SetCategory("Options")
1494+
.SetCategory("Integer Numbers default types");
1495+
1496+
ExpressionEvaluator evaluatorWithIntForceToDouble = new ExpressionEvaluator
14961497
{
14971498
OptionForceIntegerNumbersEvaluationsAsDoubleByDefault = true
1498-
}
1499-
, "(130-120)/(2*250)")
1500-
.Returns(0.02)
1501-
.SetCategory("Options")
1502-
.SetCategory("Integer Numbers default types");
1499+
};
1500+
1501+
yield return new TestCaseData(evaluatorWithIntForceToDouble
1502+
, "(130-120)/(2*250)")
1503+
.Returns(0.02)
1504+
.SetCategory("Options")
1505+
.SetCategory("Integer Numbers default types");
1506+
1507+
yield return new TestCaseData(evaluatorWithIntForceToDouble
1508+
, "Round(5.54,1)")
1509+
.Returns(5.5)
1510+
.SetCategory("Bug")
1511+
.SetCategory("Options")
1512+
.SetCategory("Integer Numbers default types");
1513+
1514+
yield return new TestCaseData(evaluatorWithIntForceToDouble
1515+
, "Round(5.54,1, MidpointRounding.ToEven)")
1516+
.Returns(5.5)
1517+
.SetCategory("Bug")
1518+
.SetCategory("Options")
1519+
.SetCategory("Integer Numbers default types");
1520+
1521+
yield return new TestCaseData(evaluatorWithIntForceToDouble
1522+
, "Round(5.54,1, MidpointRounding.AwayFromZero)")
1523+
.Returns(5.5)
1524+
.SetCategory("Bug")
1525+
.SetCategory("Options")
1526+
.SetCategory("Integer Numbers default types");
15031527

15041528
#endregion
15051529
}

CodingSeb.ExpressionEvaluator/ExpressionEvaluator.cs

Lines changed: 30 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/******************************************************************************************************
22
Title : ExpressionEvaluator (https://github.com/codingseb/ExpressionEvaluator)
3-
Version : 1.3.6.1
3+
Version : 1.3.6.2
44
(if last digit (the forth) is not a zero, the version is an intermediate version and can be unstable)
55
66
Author : Coding Seb
@@ -70,7 +70,7 @@ public class ExpressionEvaluator
7070

7171
// For script only
7272
private static readonly Regex blockKeywordsBeginningRegex = new Regex(@"^(?>\s*)(?<keyword>while|for|foreach|if|else(?>\s*)if|catch)(?>\s*)[(]", RegexOptions.IgnoreCase | RegexOptions.Compiled);
73-
private static readonly Regex foreachParenthisEvaluationRegex = new Regex(@"^(?>\s*)(?<variableName>[" + diactiticsKeywordsRegexPattern + "](?>[" + diactiticsKeywordsRegexPattern + @"0-9]*))(?>\s*)(?<in>in)(?>\s*)(?<collection>.*)", RegexOptions.IgnoreCase| RegexOptions.Compiled);
73+
private static readonly Regex foreachParenthisEvaluationRegex = new Regex(@"^(?>\s*)(?<variableName>[" + diactiticsKeywordsRegexPattern + "](?>[" + diactiticsKeywordsRegexPattern + @"0-9]*))(?>\s*)(?<in>in)(?>\s*)(?<collection>.*)", RegexOptions.IgnoreCase | RegexOptions.Compiled);
7474
private static readonly Regex blockKeywordsWithoutParenthesesBeginningRegex = new Regex(@"^(?>\s*)(?<keyword>else|do|try|finally)(?![" + diactiticsKeywordsRegexPattern + "0-9])", RegexOptions.IgnoreCase | RegexOptions.Compiled);
7575
private static readonly Regex blockBeginningRegex = new Regex(@"^(?>\s*)[{]", RegexOptions.Compiled);
7676
private static readonly Regex returnKeywordRegex = new Regex(@"^return((?>\s*)|\()", RegexOptions.IgnoreCase | RegexOptions.Singleline | RegexOptions.Compiled);
@@ -411,16 +411,25 @@ private enum TryBlockEvaluatedState
411411
},
412412
{ "Round", (self, args) =>
413413
{
414-
if(args.Count == 3) { return Math.Round(Convert.ToDouble(self.Evaluate(args[0])), (int)self.Evaluate(args[1]), (MidpointRounding)self.Evaluate(args[2])); } else if(args.Count == 2)
414+
if(args.Count == 3)
415+
{
416+
return Math.Round(Convert.ToDouble(self.Evaluate(args[0])), Convert.ToInt32(self.Evaluate(args[1])), (MidpointRounding)self.Evaluate(args[2]));
417+
}
418+
else if(args.Count == 2)
415419
{
416420
object arg2 = self.Evaluate(args[1]);
417421

418422
if(arg2 is MidpointRounding midpointRounding)
419423
return Math.Round(Convert.ToDouble(self.Evaluate(args[0])), midpointRounding);
420424
else
421-
return Math.Round(Convert.ToDouble(self.Evaluate(args[0])), (int)arg2);
425+
return Math.Round(Convert.ToDouble(self.Evaluate(args[0])), Convert.ToInt32(arg2));
426+
}
427+
else if(args.Count == 1) { return Math.Round(Convert.ToDouble(self.Evaluate(args[0]))); }
428+
else
429+
{
430+
throw new ArgumentException();
422431
}
423-
else if(args.Count == 1) { return Math.Round(Convert.ToDouble(self.Evaluate(args[0]))); } else { throw new ArgumentException(); } }
432+
}
424433
},
425434
{ "Sign", (self, args) => Math.Sign(Convert.ToDouble(self.Evaluate(args[0]))) },
426435
{ "sizeof", (self, args) =>
@@ -918,7 +927,7 @@ object ManageJumpStatementsOrExpressionEval(string expression)
918927
return lastResult;
919928
}
920929

921-
if(expression.StartsWith("throw ", StringComparisonForCasing))
930+
if (expression.StartsWith("throw ", StringComparisonForCasing))
922931
{
923932
throw Evaluate(expression.Remove(0, 6)) as Exception;
924933
}
@@ -992,9 +1001,9 @@ void ExecuteIfList()
9921001

9931002
void ExecuteTryList()
9941003
{
995-
if(tryStatementsList.Count > 0)
1004+
if (tryStatementsList.Count > 0)
9961005
{
997-
if(tryStatementsList.Count == 1)
1006+
if (tryStatementsList.Count == 1)
9981007
{
9991008
throw new ExpressionEvaluatorSyntaxErrorException("a try statement need at least one catch or one finally statement.");
10001009
}
@@ -1003,7 +1012,7 @@ void ExecuteTryList()
10031012
{
10041013
lastResult = ScriptEvaluate(tryStatementsList[0][0], ref isReturn, ref isBreak, ref isContinue);
10051014
}
1006-
catch(Exception exception)
1015+
catch (Exception exception)
10071016
{
10081017
bool atLeasOneCatch = false;
10091018

@@ -1031,14 +1040,14 @@ void ExecuteTryList()
10311040
break;
10321041
}
10331042

1034-
if(!atLeasOneCatch)
1043+
if (!atLeasOneCatch)
10351044
{
10361045
throw;
10371046
}
10381047
}
10391048
finally
10401049
{
1041-
if(tryStatementsList.Last()[0].Equals("finally"))
1050+
if (tryStatementsList.Last()[0].Equals("finally"))
10421051
{
10431052
lastResult = ScriptEvaluate(tryStatementsList.Last()[1], ref isReturn, ref isBreak, ref isContinue);
10441053
}
@@ -1167,7 +1176,7 @@ void ExecuteBlocksStacks()
11671176
ifBlockEvaluatedState = IfBlockEvaluatedState.If;
11681177
tryBlockEvaluatedState = TryBlockEvaluatedState.NoBlockEvaluated;
11691178
}
1170-
else if(keyword.Equals("try", StringComparisonForCasing))
1179+
else if (keyword.Equals("try", StringComparisonForCasing))
11711180
{
11721181
tryStatementsList.Add(new List<string>() { subScript });
11731182
ifBlockEvaluatedState = IfBlockEvaluatedState.NoBlockEvaluated;
@@ -1499,7 +1508,7 @@ private bool EvaluateNumber(string restOfExpression, Stack<object> stack, ref in
14991508
{
15001509
if (OptionForceIntegerNumbersEvaluationsAsDoubleByDefault || numberMatch.Groups["hasdecimal"].Success)
15011510
{
1502-
stack.Push(double.Parse(numberMatch.Value.Replace("_",""), NumberStyles.Any, CultureInfoForNumberParsing));
1511+
stack.Push(double.Parse(numberMatch.Value.Replace("_", ""), NumberStyles.Any, CultureInfoForNumberParsing));
15031512
}
15041513
else
15051514
{
@@ -1654,7 +1663,7 @@ void Init(object element, List<string> initArgs)
16541663

16551664
if (arrayArgs.Count > 0)
16561665
{
1657-
array = Array.CreateInstance(type, arrayArgs.ConvertAll(subExpression => (int)Evaluate(subExpression)).ToArray());
1666+
array = Array.CreateInstance(type, arrayArgs.ConvertAll(subExpression => Convert.ToInt32(Evaluate(subExpression))).ToArray());
16581667
}
16591668

16601669
Match initInNewBeginningMatch = initInNewBeginningRegex.Match(expr.Substring(i));
@@ -1685,7 +1694,7 @@ void Init(object element, List<string> initArgs)
16851694
{
16861695
return false;
16871696
}
1688-
}
1697+
}
16891698

16901699
private bool EvaluateVarOrFunc(string expr, string restOfExpression, Stack<object> stack, ref int i)
16911700
{
@@ -1761,7 +1770,7 @@ private bool EvaluateVarOrFunc(string expr, string restOfExpression, Stack<objec
17611770
else
17621771
stack.Push((dictionaryObject[varFuncName] as Delegate).DynamicInvoke(oArgs.ToArray()));
17631772
}
1764-
else if(objType.GetProperty(varFuncName, InstanceBindingFlag) is PropertyInfo instancePropertyInfo
1773+
else if (objType.GetProperty(varFuncName, InstanceBindingFlag) is PropertyInfo instancePropertyInfo
17651774
&& (instancePropertyInfo.PropertyType.IsSubclassOf(typeof(Delegate)) || instancePropertyInfo.PropertyType == typeof(Delegate)))
17661775
{
17671776
stack.Push((instancePropertyInfo.GetValue(obj) as Delegate).DynamicInvoke(oArgs.ToArray()));
@@ -2090,7 +2099,7 @@ private bool EvaluateVarOrFunc(string expr, string restOfExpression, Stack<objec
20902099
string typeName = $"{varFuncName}{((i < expr.Length && expr.Substring(i)[0] == '?') ? "?" : "") }";
20912100
Type staticType = GetTypeByFriendlyName(typeName, genericsTypes);
20922101

2093-
if(staticType == null && OptionInlineNamespacesEvaluationActive)
2102+
if (staticType == null && OptionInlineNamespacesEvaluationActive)
20942103
{
20952104
int subIndex = 0;
20962105
Match namespaceMatch = varOrFunctionRegEx.Match(expr.Substring(i + subIndex));
@@ -2109,7 +2118,7 @@ private bool EvaluateVarOrFunc(string expr, string restOfExpression, Stack<objec
21092118

21102119
staticType = GetTypeByFriendlyName(typeName, namespaceMatch.Groups["isgeneric"].Value);
21112120

2112-
if(staticType != null)
2121+
if (staticType != null)
21132122
{
21142123
i += subIndex;
21152124
break;
@@ -2776,7 +2785,7 @@ private BindingFlags DetermineInstanceOrStatic(ref Type objType, ref object obj,
27762785
{
27772786
valueTypeNestingTrace = obj as ValueTypeNestingTrace;
27782787

2779-
if(valueTypeNestingTrace != null)
2788+
if (valueTypeNestingTrace != null)
27802789
{
27812790
obj = valueTypeNestingTrace.Value;
27822791
}
@@ -3000,7 +3009,7 @@ private Type GetTypeByFriendlyName(string typeName, string genericTypes = "", bo
30003009
}
30013010
}
30023011
}
3003-
catch(ExpressionEvaluatorSyntaxErrorException)
3012+
catch (ExpressionEvaluatorSyntaxErrorException)
30043013
{
30053014
throw;
30063015
}
@@ -3125,7 +3134,7 @@ private class ValueTypeNestingTrace
31253134

31263135
public void AssignValue()
31273136
{
3128-
if(Container is ValueTypeNestingTrace valueTypeNestingTrace)
3137+
if (Container is ValueTypeNestingTrace valueTypeNestingTrace)
31293138
{
31303139
((dynamic)Member).SetValue(valueTypeNestingTrace.Value, Value);
31313140
valueTypeNestingTrace.AssignValue();

0 commit comments

Comments
 (0)