Skip to content

Commit 39bb365

Browse files
committed
Remove comments in scripts
1 parent e82fe21 commit 39bb365

File tree

9 files changed

+101
-13
lines changed

9 files changed

+101
-13
lines changed

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

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -40,12 +40,6 @@
4040
<WarningLevel>4</WarningLevel>
4141
</PropertyGroup>
4242
<ItemGroup>
43-
<Reference Include="Microsoft.VisualStudio.TestPlatform.TestFramework, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
44-
<HintPath>..\packages\MSTest.TestFramework.1.2.1\lib\net45\Microsoft.VisualStudio.TestPlatform.TestFramework.dll</HintPath>
45-
</Reference>
46-
<Reference Include="Microsoft.VisualStudio.TestPlatform.TestFramework.Extensions, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
47-
<HintPath>..\packages\MSTest.TestFramework.1.2.1\lib\net45\Microsoft.VisualStudio.TestPlatform.TestFramework.Extensions.dll</HintPath>
48-
</Reference>
4943
<Reference Include="nunit.framework, Version=3.10.1.0, Culture=neutral, PublicKeyToken=2638cd05610744eb, processorArchitecture=MSIL">
5044
<HintPath>..\packages\NUnit.3.10.1\lib\net45\nunit.framework.dll</HintPath>
5145
</Reference>

CodingSeb.ExpressionEvaluator.Tests/ExpressionEvaluatorScriptEvaluateTests.cs

Lines changed: 52 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
11
using NUnit.Framework;
2-
using Should;
3-
using System;
42
using System.Collections.Generic;
53
using System.Text.RegularExpressions;
64

@@ -11,21 +9,30 @@ public class ExpressionEvaluatorScriptEvaluateTests
119
{
1210
private static Regex removeAllWhiteSpacesRegex = new Regex(@"\s+");
1311

12+
#region Scripts that must succeed
13+
1414
public static IEnumerable<TestCaseData> TestCasesForScriptEvaluateTests
1515
{
1616
get
1717
{
18-
// while
18+
#region while
19+
1920
yield return new TestCaseData(Resources.Script0001 , null, true).SetCategory("Script").SetCategory("while").SetCategory("variable assignation").SetCategory("++").SetCategory("+=").Returns("0,1,2,3,4");
2021
yield return new TestCaseData(removeAllWhiteSpacesRegex.Replace(Resources.Script0001, "") , null, true).SetCategory("Script").SetCategory("while").SetCategory("variable assignation").SetCategory("++").SetCategory("+=").Returns("0,1,2,3,4");
2122

22-
// for
23+
#endregion
24+
25+
#region for
26+
2327
yield return new TestCaseData(Resources.Script0002 , null, true).SetCategory("Script").SetCategory("for").SetCategory("variable assignation").SetCategory("++").SetCategory("+=").Returns("0,1,2,3,4");
2428
yield return new TestCaseData(removeAllWhiteSpacesRegex.Replace(Resources.Script0002, "") , null, true).SetCategory("Script").SetCategory("for").SetCategory("variable assignation").SetCategory("++").SetCategory("+=").Returns("0,1,2,3,4");
2529
yield return new TestCaseData(Resources.Script0003 , null, true).SetCategory("Script").SetCategory("for").SetCategory("variable assignation").SetCategory("++").SetCategory("+=").Returns("0,1,2,3,4");
2630
yield return new TestCaseData(removeAllWhiteSpacesRegex.Replace(Resources.Script0003, "") , null, true).SetCategory("Script").SetCategory("for").SetCategory("variable assignation").SetCategory("++").SetCategory("+=").Returns("0,1,2,3,4");
2731

28-
// if, else if, else
32+
#endregion
33+
34+
#region if, else if, else
35+
2936
yield return new TestCaseData(Resources.Script0004.Replace("[valx]", "0").Replace("[valy]", "1") , null, true).SetCategory("Script").SetCategory("if").SetCategory("variable assignation").Returns(1);
3037
yield return new TestCaseData(removeAllWhiteSpacesRegex.Replace(Resources.Script0004.Replace("[valx]", "0").Replace("[valy]", "1"), "").Replace("else", "else ") , null, true).SetCategory("Script").SetCategory("if").SetCategory("variable assignation").Returns(1);
3138
yield return new TestCaseData(Resources.Script0004.Replace("[valx]", "-1").Replace("[valy]", "1") , null, true).SetCategory("Script").SetCategory("if").SetCategory("variable assignation").Returns(1);
@@ -57,6 +64,8 @@ public static IEnumerable<TestCaseData> TestCasesForScriptEvaluateTests
5764

5865
yield return new TestCaseData(Resources.Script0005.Replace("[valx]", "1").Replace("[valy]", "0"), null, true).SetCategory("Script").SetCategory("if").SetCategory("variable assignation").Returns(4);
5966
yield return new TestCaseData(removeAllWhiteSpacesRegex.Replace(Resources.Script0005.Replace("[valx]", "1").Replace("[valy]", "0"), "").Replace("else", "else "), null, true).SetCategory("Script").SetCategory("if").SetCategory("variable assignation").Returns(4);
67+
68+
#endregion
6069
}
6170
}
6271

@@ -73,5 +82,43 @@ public object TestCasesForScriptEvaluate(string script, Dictionary<string, objec
7382

7483
return evaluator.ScriptEvaluate(script);
7584
}
85+
86+
#endregion
87+
88+
#region Remove Comments
89+
90+
public static IEnumerable<TestCaseData> TestCasesForRemoveCommentsTests
91+
{
92+
get
93+
{
94+
yield return new TestCaseData("// simple line comment").SetCategory("RemoveComments").Returns(" ");
95+
yield return new TestCaseData("/* simple block comment */").SetCategory("RemoveComments").Returns(" ");
96+
yield return new TestCaseData("/* multi line\r\nblock comment */").SetCategory("RemoveComments").Returns("\r\n");
97+
yield return new TestCaseData("/* multi line\rblock comment */").SetCategory("RemoveComments").Returns("\r");
98+
yield return new TestCaseData("/* multi line\nblock comment */").SetCategory("RemoveComments").Returns("\n");
99+
yield return new TestCaseData(@"a = ""apple""; // test").SetCategory("RemoveComments").Returns(@"a = ""apple""; ");
100+
yield return new TestCaseData(@"a = ""apple""; /* test */").SetCategory("RemoveComments").Returns(@"a = ""apple""; ");
101+
yield return new TestCaseData(@"// /*comment within comments */").SetCategory("RemoveComments").Returns(@" ");
102+
yield return new TestCaseData(@"/* //comment within comments */").SetCategory("RemoveComments").Returns(@" ");
103+
yield return new TestCaseData(@"// bla bla /*comment within comments */ bla bla").SetCategory("RemoveComments").Returns(@" ");
104+
yield return new TestCaseData(@"/* bla bla //comment within comments */").SetCategory("RemoveComments").Returns(@" ");
105+
yield return new TestCaseData(@"// ""bla bla"" ").SetCategory("RemoveComments").Returns(@" ");
106+
yield return new TestCaseData(@"/* ""bla bla"" */").SetCategory("RemoveComments").Returns(@" ");
107+
yield return new TestCaseData(@"""// test """).SetCategory("RemoveComments").SetCategory("Not a comments").Returns(@"""// test """);
108+
yield return new TestCaseData(@"""/* test */""").SetCategory("RemoveComments").SetCategory("Not a comments").Returns(@"""/* test */""");
109+
yield return new TestCaseData(@"""bla bla // test """).SetCategory("RemoveComments").SetCategory("Not a comments").Returns(@"""bla bla // test """);
110+
yield return new TestCaseData(@"""bla bla /* test */ bla bla""").SetCategory("RemoveComments").SetCategory("Not a comments").Returns(@"""bla bla /* test */ bla bla""");
111+
}
112+
}
113+
114+
[TestCaseSource(nameof(TestCasesForRemoveCommentsTests))]
115+
public string RemoveCommentsTests(string script)
116+
{
117+
ExpressionEvaluator evaluator = new ExpressionEvaluator();
118+
119+
return evaluator.RemoveComments(script);
120+
}
121+
122+
#endregion
76123
}
77124
}

CodingSeb.ExpressionEvaluator.Tests/Resources/Script0001.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
// Script0001
12
x = 0;
23
result = "";
34

CodingSeb.ExpressionEvaluator.Tests/Resources/Script0002.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
// Script0002
12
result = "";
23

34
for(x = 0; x < 5;x++)

CodingSeb.ExpressionEvaluator.Tests/Resources/Script0003.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
// Script0003
12
result = "";
23

34
for(x = 0; x < 5;x++)

CodingSeb.ExpressionEvaluator.Tests/Resources/Script0004.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
// Script0004
12
x = [valx];
23
y = [valy];
34
result = 0;

CodingSeb.ExpressionEvaluator.Tests/Resources/Script0005.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
// Script0005
12
x = [valx];
23
y = [valy];
34
result = 0;

CodingSeb.ExpressionEvaluator.Tests/packages.config

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
<?xml version="1.0" encoding="utf-8"?>
22
<packages>
3-
<package id="MSTest.TestAdapter" version="1.2.1" targetFramework="net45" />
4-
<package id="MSTest.TestFramework" version="1.2.1" targetFramework="net45" />
53
<package id="NUnit" version="3.10.1" targetFramework="net45" />
64
<package id="NUnit3TestAdapter" version="3.10.0" targetFramework="net45" />
75
<package id="Should" version="1.1.20" targetFramework="net45" />

CodingSeb.ExpressionEvaluator/ExpressionEvaluator.cs

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,14 @@ public class ExpressionEvaluator
3333
private static readonly string primaryTypesRegexPattern = @"(?<=^|[^a-zA-Z_])(?<primaryType>object|string|bool[?]?|byte[?]?|char[?]?|decimal[?]?|double[?]?|short[?]?|int[?]?|long[?]?|sbyte[?]?|float[?]?|ushort[?]?|uint[?]?|void)(?=[^a-zA-Z_]|$)";
3434
private Regex primaryTypesRegex = new Regex(primaryTypesRegexPattern);
3535

36+
// To remove comments in scripts based on https://stackoverflow.com/questions/3524317/regex-to-strip-line-comments-from-c-sharp/3524689#3524689
37+
private static readonly string blockComments = @"/\*(.*?)\*/";
38+
private static readonly string lineComments = @"//[^\r\n]*";
39+
private static readonly string stringsIgnore = @"""((\\[^\n]|[^""\n])*)""";
40+
private static readonly string verbatimStringsIgnore = @"@(""[^""]*"")+";
41+
private static readonly Regex removeCommentsRegex = new Regex($"{blockComments}|{lineComments}|{stringsIgnore}|{verbatimStringsIgnore}", RegexOptions.Singleline);
42+
private static readonly Regex newLineCharsRegex = new Regex(@"\r\n|\r|\n");
43+
3644
// For script only
3745
private static Regex variableAssignationRegex = new Regex(@"^(?<name>[a-zA-Z_][a-zA-Z0-9_]*)\s*(?<assignmentPrefix>[+\-*/%&|^]|<<|>>)?=(?![=>])");
3846
private static Regex blockKeywordsBeginningRegex = new Regex(@"^\s*(?<keyword>while|for|if|else\s+if)\s*[(]", RegexOptions.IgnoreCase);
@@ -623,6 +631,7 @@ public ExpressionEvaluator(Dictionary<string, object> variables) : this()
623631
/// <returns>The result of the last evaluated expression</returns>
624632
public object ScriptEvaluate(string script)
625633
{
634+
script = RemoveComments(script);
626635
object lastResult = null;
627636
int startOfExpression = 0;
628637
IfBlockEvaluatedState ifBlockEvaluatedState = IfBlockEvaluatedState.NoBlockEvaluated;
@@ -1692,6 +1701,41 @@ private object ProcessStack(Stack<object> stack)
16921701

16931702
#endregion
16941703

1704+
#region Remove comments
1705+
1706+
/// <summary>
1707+
/// remove all line and blocks comments of the specified C# script. (Manage in strings comment syntax ignore)
1708+
/// based on https://stackoverflow.com/questions/3524317/regex-to-strip-line-comments-from-c-sharp/3524689#3524689
1709+
/// </summary>
1710+
/// <param name="scriptWithComments">The C# code with comments to remove</param>
1711+
/// <returns>The same C# code without comments</returns>
1712+
public string RemoveComments(string scriptWithComments)
1713+
{
1714+
return removeCommentsRegex.Replace(scriptWithComments,
1715+
match =>
1716+
{
1717+
if(match.Value.StartsWith("/"))
1718+
{
1719+
Match newLineCharsMatch = newLineCharsRegex.Match(match.Value);
1720+
1721+
if(match.Value.StartsWith("/*") && newLineCharsMatch.Success)
1722+
{
1723+
return newLineCharsMatch.Value;
1724+
}
1725+
else
1726+
{
1727+
return " ";
1728+
}
1729+
}
1730+
else
1731+
{
1732+
return match.Value;
1733+
}
1734+
});
1735+
}
1736+
1737+
#endregion
1738+
16951739
#region Utils methods for parsing and interpretation
16961740

16971741
private delegate dynamic lambdaExpressionDelegate(params dynamic[] args);

0 commit comments

Comments
 (0)