Skip to content

Commit 57279fc

Browse files
committed
Indexing postfix operators ++ and --
1 parent 85ee127 commit 57279fc

File tree

6 files changed

+112
-90
lines changed

6 files changed

+112
-90
lines changed

CodingSeb.ExpressionEvaluator.Tests/CodingSeb.ExpressionEvaluator.Tests.csproj

+3
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,9 @@
113113
<ItemGroup>
114114
<None Include="Resources\Script0011.txt" />
115115
</ItemGroup>
116+
<ItemGroup>
117+
<None Include="Resources\Script0012.txt" />
118+
</ItemGroup>
116119
<Import Project="$(VSToolsPath)\TeamTest\Microsoft.TestTools.targets" Condition="Exists('$(VSToolsPath)\TeamTest\Microsoft.TestTools.targets')" />
117120
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
118121
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">

CodingSeb.ExpressionEvaluator.Tests/ExpressionEvaluatorScriptEvaluateTests.cs

+28-21
Original file line numberDiff line numberDiff line change
@@ -566,27 +566,6 @@ public static IEnumerable<TestCaseData> TestCasesForScriptEvaluateTests
566566

567567
#endregion
568568

569-
#region Indexing Assignation
570-
571-
yield return new TestCaseData(Resources.Script0011, null, null, null)
572-
.SetCategory("Script")
573-
.SetCategory("Indexing assignation")
574-
.SetCategory("=")
575-
.SetCategory("+=")
576-
.SetCategory("-=")
577-
.SetCategory("*=")
578-
.SetCategory("/=")
579-
.SetCategory("/=")
580-
.SetCategory("%=")
581-
.SetCategory("^=")
582-
.SetCategory("&=")
583-
.SetCategory("|=")
584-
.SetCategory("<<=")
585-
.SetCategory("<<=")
586-
.SetCategory("List function")
587-
.Returns("[8,11,3,15,2,1,6,1,7,20,1]");
588-
#endregion
589-
590569
#endregion
591570

592571
#region while
@@ -954,6 +933,34 @@ public static IEnumerable<TestCaseData> TestCasesForScriptEvaluateTests
954933
.SetCategory("break in while")
955934
.Returns("0,1,2,4,5,6,");
956935

936+
yield return new TestCaseData(Resources.Script0011, null, null, null)
937+
.SetCategory("Script")
938+
.SetCategory("Indexing assignation")
939+
.SetCategory("=")
940+
.SetCategory("+=")
941+
.SetCategory("-=")
942+
.SetCategory("*=")
943+
.SetCategory("/=")
944+
.SetCategory("/=")
945+
.SetCategory("%=")
946+
.SetCategory("^=")
947+
.SetCategory("&=")
948+
.SetCategory("|=")
949+
.SetCategory("<<=")
950+
.SetCategory("<<=")
951+
.SetCategory("List function")
952+
.Returns("[8,11,3,15,2,1,6,1,7,20,1]");
953+
954+
yield return new TestCaseData(Resources.Script0012, null, null, null)
955+
.SetCategory("Script")
956+
.SetCategory("Indexing postfix operators")
957+
.SetCategory("=")
958+
.SetCategory("+=")
959+
.SetCategory("++")
960+
.SetCategory("--")
961+
.SetCategory("List function")
962+
.Returns("[6,4,10,6,10,4]");
963+
957964
#endregion
958965
}
959966
}

CodingSeb.ExpressionEvaluator.Tests/Resources.Designer.cs

+38-16
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

CodingSeb.ExpressionEvaluator.Tests/Resources.resx

+3
Original file line numberDiff line numberDiff line change
@@ -151,4 +151,7 @@
151151
<data name="Script0011" type="System.Resources.ResXFileRef, System.Windows.Forms">
152152
<value>resources\script0011.txt;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;Windows-1252</value>
153153
</data>
154+
<data name="Script0012" type="System.Resources.ResXFileRef, System.Windows.Forms">
155+
<value>resources\script0012.txt;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;Windows-1252</value>
156+
</data>
154157
</root>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
/* Script0012 */
2+
list = List(5,5,5,5,5,5);
3+
4+
list[0]++;
5+
list[1]--;
6+
list[2] += list[3]++;
7+
list[4] += list[5]--;
8+
9+
return list.Json;

CodingSeb.ExpressionEvaluator/ExpressionEvaluator.cs

+31-53
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ public class ExpressionEvaluator
2222
private static readonly Regex internalCharRegex = new Regex(@"^['](\\[']|[^'])*[']");
2323
private static readonly Regex castRegex = new Regex(@"^\(\s*(?<typeName>[a-zA-Z_][a-zA-Z0-9_\.\[\]<>]*[?]?)\s*\)");
2424
private static readonly Regex indexingBeginningRegex = new Regex(@"^[?]?\[");
25-
private static readonly Regex assignationOperatorRegex = new Regex(@"^\s*(?<assignmentPrefix>[+\-*/%&|^]|<<|>>)?=(?![=>])");
25+
private static readonly Regex assignationOrPostFixOperatorRegex = new Regex(@"^\s*((?<assignmentPrefix>[+\-*/%&|^]|<<|>>)?=(?![=>])|(?<postfixOperator>([+][+]|--)(?![a-zA-Z0-9_])))");
2626
private static readonly Regex endOfStringWithDollar = new Regex("^[^\"{]*[\"{]");
2727
private static readonly Regex endOfStringWithoutDollar = new Regex("^[^\"]*[\"]");
2828
private static readonly Regex endOfStringInterpolationRegex = new Regex("^[^}\"]*[}\"]");
@@ -1642,42 +1642,50 @@ private bool EvaluateIndexing(string expr, string s, Stack<object> stack, ref in
16421642
ExpressionOperator op = indexingBeginningMatch.Length == 2 ? ExpressionOperator.IndexingWithNullConditional : ExpressionOperator.Indexing;
16431643
dynamic left = stack.Pop();
16441644

1645-
Match assignationOperatorMatch;
1645+
Match assignationOrPostFixOperatorMatch = assignationOrPostFixOperatorRegex.Match(expr.Substring(i + 1));
16461646

16471647
object valueToPush = null;
16481648

1649-
if ((assignationOperatorMatch = assignationOperatorRegex.Match(expr.Substring(i + 1))).Success)
1649+
if (assignationOrPostFixOperatorMatch.Success)
16501650
{
1651-
i += assignationOperatorMatch.Length + 1;
1651+
i += assignationOrPostFixOperatorMatch.Length + 1;
16521652

1653-
if (stack.Count > 1)
1654-
throw new ExpressionEvaluatorSyntaxErrorException("The left part of an assignation must be a variable, a property or an indexer.");
1653+
bool postFixoperator = assignationOrPostFixOperatorMatch.Groups["postfixOperator"].Success;
1654+
string exceptionContext = postFixoperator ? "++ or -- operator" : "an assignation";
16551655

1656-
string rightExpression = expr.Substring(i);
1657-
i = expr.Length;
1656+
if (stack.Count > 1)
1657+
throw new ExpressionEvaluatorSyntaxErrorException($"The left part of {exceptionContext} must be a variable, a property or an indexer.");
16581658

16591659
if (op == ExpressionOperator.IndexingWithNullConditional)
1660-
throw new ExpressionEvaluatorSyntaxErrorException("Null coalescing is not usable left to an assignation");
1661-
1662-
if (rightExpression.Trim().Equals(string.Empty))
1663-
throw new ExpressionEvaluatorSyntaxErrorException("Right part is missing in assignation");
1660+
throw new ExpressionEvaluatorSyntaxErrorException($"Null coalescing is not usable left to {exceptionContext}");
16641661

1665-
if (assignationOperatorMatch.Groups["assignmentPrefix"].Success)
1662+
if (postFixoperator)
1663+
valueToPush = assignationOrPostFixOperatorMatch.Groups["postfixOperator"].Value.Equals("++") ? left[right]++ : left[right]--;
1664+
else
16661665
{
1667-
ExpressionOperator prefixOp = operatorsDictionary[assignationOperatorMatch.Groups["assignmentPrefix"].Value];
1666+
string rightExpression = expr.Substring(i);
1667+
i = expr.Length;
16681668

1669-
valueToPush = operatorsEvaluations[0][op](left, right);
1669+
if (rightExpression.Trim().Equals(string.Empty))
1670+
throw new ExpressionEvaluatorSyntaxErrorException("Right part is missing in assignation");
16701671

1671-
valueToPush = operatorsEvaluations.Find(dict => dict.ContainsKey(prefixOp))[prefixOp](valueToPush, Evaluate(rightExpression));
1672-
}
1673-
else
1674-
{
1675-
valueToPush = Evaluate(rightExpression);
1676-
}
1672+
if (assignationOrPostFixOperatorMatch.Groups["assignmentPrefix"].Success)
1673+
{
1674+
ExpressionOperator prefixOp = operatorsDictionary[assignationOrPostFixOperatorMatch.Groups["assignmentPrefix"].Value];
16771675

1678-
left[right] = valueToPush;
1676+
valueToPush = operatorsEvaluations[0][op](left, right);
16791677

1680-
stack.Clear();
1678+
valueToPush = operatorsEvaluations.Find(dict => dict.ContainsKey(prefixOp))[prefixOp](valueToPush, Evaluate(rightExpression));
1679+
}
1680+
else
1681+
{
1682+
valueToPush = Evaluate(rightExpression);
1683+
}
1684+
1685+
left[right] = valueToPush;
1686+
1687+
stack.Clear();
1688+
}
16811689
}
16821690
else
16831691
{
@@ -2324,36 +2332,6 @@ private void GetCodeUntilEndOfString(string subExpr, Match stringBeginningMatch,
23242332
}
23252333
}
23262334

2327-
//private string GetCodeUntilEndOfStringInterpolation(string subExpr)
2328-
//{
2329-
// Match endOfStringInterpolationMatch = endOfStringInterpolationRegex.Match(subExpr);
2330-
// StringBuilder result = new StringBuilder();
2331-
2332-
// if (endOfStringInterpolationMatch.Success)
2333-
// {
2334-
// if (endOfStringInterpolationMatch.Value.EndsWith("}"))
2335-
// {
2336-
// result.Append(endOfStringInterpolationMatch.Value);
2337-
// }
2338-
// else
2339-
// {
2340-
// Match stringBeginningForEndBlockMatch = stringBeginningForEndBlockRegex.Match(endOfStringInterpolationMatch.Value);
2341-
2342-
// string subString = GetCodeUntilEndOfString(subExpr.Substring(endOfStringInterpolationMatch.Length), stringBeginningForEndBlockMatch);
2343-
2344-
// result.Append(endOfStringInterpolationMatch.Value);
2345-
// result.Append(subString);
2346-
// result.Append(GetCodeUntilEndOfStringInterpolation(subExpr.Substring(endOfStringInterpolationMatch.Length + subString.Length)));
2347-
// }
2348-
// }
2349-
// else
2350-
// {
2351-
// result.Append(subExpr);
2352-
// }
2353-
2354-
// return result.ToString();
2355-
//}
2356-
23572335
private string GetCodeUntilEndOfStringInterpolation(string subExpr)
23582336
{
23592337
Match endOfStringInterpolationMatch = endOfStringInterpolationRegex.Match(subExpr);

0 commit comments

Comments
 (0)