Skip to content

Commit cd6f3d3

Browse files
author
Sébastien Geiser
committed
Correction of Last expression with semicolon before a block end with line return and OptionScriptNeedSemicolonAtTheEndOfLastExpression.
+ TypedVariables in progress
1 parent f8eefa2 commit cd6f3d3

File tree

9 files changed

+147
-8
lines changed

9 files changed

+147
-8
lines changed

CodingSeb.ExpressionEvaluator.Tests/ExpressionEvaluatorScriptEvaluateTests.cs

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1260,6 +1260,41 @@ public static IEnumerable<TestCaseData> TestCasesForScriptEvaluateTests
12601260

12611261
#endregion
12621262

1263+
#region Typed and dynamic variables
1264+
1265+
yield return new TestCaseData(Resources.Script0063, null, null, null, null)
1266+
.SetCategory("Script")
1267+
.SetCategory("primaryTyped variable")
1268+
.SetCategory("int")
1269+
.SetCategory("=")
1270+
.Returns(5);
1271+
1272+
yield return new TestCaseData(Resources.Script0064, null, null, null, null)
1273+
.SetCategory("Script")
1274+
.SetCategory("primaryTyped variable")
1275+
.SetCategory("float")
1276+
.SetCategory("=")
1277+
.Returns(5.5);
1278+
1279+
yield return new TestCaseData(Resources.Script0065, null, null, null, null)
1280+
.SetCategory("Script")
1281+
.SetCategory("Dynamic variable")
1282+
.SetCategory("dynamic")
1283+
.SetCategory("=")
1284+
.Returns(8);
1285+
1286+
yield return new TestCaseData(Resources.Script0066, null, null, null, null)
1287+
.SetCategory("Script")
1288+
.SetCategory("primaryTyped variable")
1289+
.SetCategory("string")
1290+
.SetCategory("int")
1291+
.SetCategory("for")
1292+
.SetCategory("++")
1293+
.SetCategory("=")
1294+
.Returns("0,1,2,3,4,");
1295+
1296+
#endregion
1297+
12631298
#region More complex script
12641299

12651300
yield return new TestCaseData(Resources.Script0007, null, null, null, null)
@@ -1404,6 +1439,17 @@ public static IEnumerable<TestCaseData> TestCasesForScriptEvaluateTests
14041439
.SetCategory("Better Than C#")
14051440
.Returns("Result Hey 9, 5");
14061441

1442+
yield return new TestCaseData(Resources.Script0066, new ExpressionEvaluator { OptionScriptNeedSemicolonAtTheEndOfLastExpression = false }, null, null, null)
1443+
.SetCategory("Script")
1444+
.SetCategory("primaryTyped variable")
1445+
.SetCategory("string")
1446+
.SetCategory("int")
1447+
.SetCategory("for")
1448+
.SetCategory("++")
1449+
.SetCategory("=")
1450+
.SetCategory("OptionScriptNeedSemicolonAtTheEndOfLastExpression")
1451+
.Returns("0,1,2,3,4,");
1452+
14071453
#endregion
14081454
}
14091455
}

CodingSeb.ExpressionEvaluator.Tests/OthersTests.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
namespace CodingSeb.ExpressionEvaluator.Tests
55
{
6+
[TestFixture]
67
public class OthersTests
78
{
89
[Test]

CodingSeb.ExpressionEvaluator.Tests/Resources.Designer.cs

Lines changed: 53 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

CodingSeb.ExpressionEvaluator.Tests/Resources.resx

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -304,4 +304,16 @@
304304
<data name="Script0062" type="System.Resources.ResXFileRef, System.Windows.Forms">
305305
<value>resources\script0062.txt;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8</value>
306306
</data>
307+
<data name="Script0063" type="System.Resources.ResXFileRef, System.Windows.Forms">
308+
<value>resources\script0063.txt;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8</value>
309+
</data>
310+
<data name="Script0064" type="System.Resources.ResXFileRef, System.Windows.Forms">
311+
<value>resources\script0064.txt;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8</value>
312+
</data>
313+
<data name="Script0065" type="System.Resources.ResXFileRef, System.Windows.Forms">
314+
<value>resources\script0065.txt;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8</value>
315+
</data>
316+
<data name="Script0066" type="System.Resources.ResXFileRef, System.Windows.Forms">
317+
<value>resources\script0066.txt;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8</value>
318+
</data>
307319
</root>
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
/* Script0063 */
2+
int x = 3;
3+
4+
return x + 2;
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
/* Script0064 */
2+
float x = 3.5f;
3+
4+
return x + 2;
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
/* Script0065 */
2+
dynamic x = 6;
3+
4+
return x + 2;
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
/* Script0066 */
2+
string test = "";
3+
4+
for(int x = 0; x < 5; x++)
5+
{
6+
test += x.ToString() + ",";
7+
}
8+
9+
return test;

CodingSeb.ExpressionEvaluator/ExpressionEvaluator.cs

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,10 @@ public partial class ExpressionEvaluator
3030

3131
protected const string diactitics = "áàâãåǎăāąæéèêëěēĕėęěìíîïīĭįijóôõöōŏőøðœùúûüǔũūŭůűųýþÿŷıćĉċčçďđĝğġģĥħĵķĺļľŀłńņňŋñŕŗřśŝşšţťŧŵźżžÁÀÂÃÅǍĂĀĄÆÉÈÊËĚĒĔĖĘĚÌÍÎÏĪĬĮIJÓÔÕÖŌŎŐØÐŒÙÚÛÜǓŨŪŬŮŰŲÝÞŸŶIĆĈĊČÇĎĐĜĞĠĢĤĦĴĶĹĻĽĿŁŃŅŇŊÑŔŖŘŚŜŞŠŢŤŦŴŹŻŽß";
3232
protected const string diactiticsKeywordsRegexPattern = "a-zA-Z_" + diactitics;
33+
protected const string primaryTypesGroupPattern = "(?<primaryType>object|string|bool[?]?|byte[?]?|char[?]?|decimal[?]?|double[?]?|short[?]?|int[?]?|long[?]?|sbyte[?]?|float[?]?|ushort[?]?|uint[?]?|ulong[?]?|void)";
34+
protected const string primaryTypesRegexPattern = "(?<=^|[^" + diactiticsKeywordsRegexPattern + "])" + primaryTypesGroupPattern + "(?=[^a-zA-Z_]|$)";
3335

34-
protected static readonly Regex varOrFunctionRegEx = new Regex($@"^((?<sign>[+-])|(?<prefixOperator>[+][+]|--)|(?<varKeyword>var\s+)|(?<inObject>(?<nullConditional>[?])?\.)?)(?<name>[{ diactiticsKeywordsRegexPattern }](?>[{ diactiticsKeywordsRegexPattern }0-9]*))(?>\s*)((?<assignationOperator>(?<assignmentPrefix>[+\-*/%&|^]|<<|>>)?=(?![=>]))|(?<postfixOperator>([+][+]|--)(?![{ diactiticsKeywordsRegexPattern}0-9]))|((?<isgeneric>[<](?>([{ diactiticsKeywordsRegexPattern }](?>[{ diactiticsKeywordsRegexPattern }0-9]*)|(?>\s+)|[,\.])+|(?<gentag>[<])|(?<-gentag>[>]))*(?(gentag)(?!))[>])?(?<isfunction>[(])?))", RegexOptions.IgnoreCase | RegexOptions.Compiled);
36+
protected static readonly Regex varOrFunctionRegEx = new Regex($@"^((?<sign>[+-])|(?<prefixOperator>[+][+]|--)|(?<varKeyword>var)\s+|(?<dynamicKeyword>dynamic)\s+|{primaryTypesGroupPattern}\s+|(?<inObject>(?<nullConditional>[?])?\.)?)(?<name>[{ diactiticsKeywordsRegexPattern }](?>[{ diactiticsKeywordsRegexPattern }0-9]*))(?>\s*)((?<assignationOperator>(?<assignmentPrefix>[+\-*/%&|^]|<<|>>)?=(?![=>]))|(?<postfixOperator>([+][+]|--)(?![{ diactiticsKeywordsRegexPattern}0-9]))|((?<isgeneric>[<](?>([{ diactiticsKeywordsRegexPattern }](?>[{ diactiticsKeywordsRegexPattern }0-9]*)|(?>\s+)|[,\.])+|(?<gentag>[<])|(?<-gentag>[>]))*(?(gentag)(?!))[>])?(?<isfunction>[(])?))", RegexOptions.IgnoreCase | RegexOptions.Compiled);
3537

3638
protected const string numberRegexOrigPattern = @"^(?<sign>[+-])?([0-9][0-9_{1}]*[0-9]|\d)(?<hasdecimal>{0}?([0-9][0-9_]*[0-9]|\d)(e[+-]?([0-9][0-9_]*[0-9]|\d))?)?(?<type>ul|[fdulm])?";
3739
protected string numberRegexPattern = null;
@@ -58,8 +60,6 @@ public partial class ExpressionEvaluator
5860
protected string InstanceCreationWithNewKeywordRegexPattern { get { return $@"^new(?>\s*)((?<isAnonymous>[{{])|((?<name>[{ diactiticsKeywordsRegexPattern }][{ diactiticsKeywordsRegexPattern}0-9{ (OptionInlineNamespacesEvaluationActive ? @"\." : string.Empty) }]*)(?>\s*)(?<isgeneric>[<](?>[^<>]+|(?<gentag>[<])|(?<-gentag>[>]))*(?(gentag)(?!))[>])?(?>\s*)((?<isfunction>[(])|(?<isArray>\[)|(?<isInit>[{{]))?))"; } }
5961
protected string CastRegexPattern { get { return $@"^\((?>\s*)(?<typeName>[{ diactiticsKeywordsRegexPattern }][{ diactiticsKeywordsRegexPattern }0-9{ (OptionInlineNamespacesEvaluationActive ? @"\." : string.Empty) }\[\]<>]*[?]?)(?>\s*)\)"; } }
6062

61-
protected const string primaryTypesRegexPattern = "(?<=^|[^" + diactiticsKeywordsRegexPattern + "])(?<primaryType>object|string|bool[?]?|byte[?]?|char[?]?|decimal[?]?|double[?]?|short[?]?|int[?]?|long[?]?|sbyte[?]?|float[?]?|ushort[?]?|uint[?]?|ulong[?]?|void)(?=[^a-zA-Z_]|$)";
62-
6363
// To remove comments in scripts based on https://stackoverflow.com/questions/3524317/regex-to-strip-line-comments-from-c-sharp/3524689#3524689
6464
protected const string blockComments = @"/\*(.*?)\*/";
6565
protected const string lineComments = @"//[^\r\n]*";
@@ -950,6 +950,8 @@ protected virtual object ScriptEvaluate(string script, ref bool valueReturned, r
950950
List<List<string>> ifElseStatementsList = new List<List<string>>();
951951
List<List<string>> tryStatementsList = new List<List<string>>();
952952

953+
script = script.TrimEnd();
954+
953955
object ManageJumpStatementsOrExpressionEval(string expression)
954956
{
955957
expression = expression.Trim();
@@ -1343,16 +1345,20 @@ void forAction(int index)
13431345
{
13441346
ExecuteBlocksStacks();
13451347

1346-
if (TryParseStringAndParenthisAndCurlyBrackets(ref i)) { }
1348+
bool executed = false;
1349+
1350+
if (TryParseStringAndParenthisAndCurlyBrackets(ref i)){}
13471351
else if (script.Length - i > 2 && script.Substring(i, 3).Equals("';'"))
13481352
{
13491353
i += 2;
13501354
}
13511355
else if (script[i] == ';')
13521356
{
13531357
lastResult = ScriptExpressionEvaluate(ref i);
1358+
executed = true;
13541359
}
1355-
else if (!OptionScriptNeedSemicolonAtTheEndOfLastExpression && i == script.Length - 1)
1360+
1361+
if (!OptionScriptNeedSemicolonAtTheEndOfLastExpression && i == script.Length - 1 && !executed)
13561362
{
13571363
i++;
13581364
lastResult = ScriptExpressionEvaluate(ref i);
@@ -1362,12 +1368,12 @@ void forAction(int index)
13621368
ifBlockEvaluatedState = IfBlockEvaluatedState.NoBlockEvaluated;
13631369
tryBlockEvaluatedState = TryBlockEvaluatedState.NoBlockEvaluated;
13641370

1365-
if (OptionScriptNeedSemicolonAtTheEndOfLastExpression || i < script.Length - 1)
1371+
if (OptionScriptNeedSemicolonAtTheEndOfLastExpression || i < script.Length)
13661372
i++;
13671373
}
13681374
}
13691375

1370-
if (!script.Substring(startOfExpression).Trim().Equals(string.Empty) && !isReturn && !isBreak && !isContinue)
1376+
if (!script.Substring(startOfExpression).Trim().Equals(string.Empty) && !isReturn && !isBreak && !isContinue && OptionScriptNeedSemicolonAtTheEndOfLastExpression)
13711377
throw new ExpressionEvaluatorSyntaxErrorException("A [;] character is missing.");
13721378

13731379
ExecuteBlocksStacks();
@@ -1718,7 +1724,7 @@ protected virtual bool EvaluateVarOrFunc(string expression, Stack<object> stack,
17181724
if (varFuncMatch.Groups["varKeyword"].Success
17191725
&& !varFuncMatch.Groups["assignationOperator"].Success)
17201726
{
1721-
throw new ExpressionEvaluatorSyntaxErrorException("Implicit variables must be initialized");
1727+
throw new ExpressionEvaluatorSyntaxErrorException("Implicit variables must be initialized. [var " + varFuncMatch.Groups["name"].Value + "]");
17221728
}
17231729

17241730
if (varFuncMatch.Success

0 commit comments

Comments
 (0)