Skip to content

Commit ab6b5c4

Browse files
committed
Fix operators
Addresses sarbian#110 Operators are now parsed like commands, removed from the regex.
1 parent 368ce9a commit ab6b5c4

6 files changed

Lines changed: 180 additions & 32 deletions

File tree

ModuleManager/MMPatchLoader.cs

Lines changed: 18 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -712,10 +712,7 @@ private static void PurgeUnused()
712712
#region Applying Patches
713713

714714
// Name is group 1, index is group 2, vector related filed is group 3, vector separator is group 4, operator is group 5
715-
private static Regex parseValue = new Regex(@"([\w\&\-\.\?\*+/^!\(\) ]+(?:,[^*\d][\w\&\-\.\?\*\(\) ]*)*)(?:,(-?[0-9\*]+))?(?:\[((?:[0-9\*]+)+)(?:,(.))?\])?(?:\s*([+\-*/^!]))?");
716-
717-
// Path is group 1, operator is group 5
718-
private static Regex parseAssign = new Regex(@"(.*)(?:\s)+([+\-*/^!])?");
715+
private static Regex parseValue = new Regex(@"([\w\&\-\.\?\*+/^!\(\) ]+(?:,[^*\d][\w\&\-\.\?\*\(\) ]*)*)(?:,(-?[0-9\*]+))?(?:\[((?:[0-9\*]+)+)(?:,(.))?\])?");
719716

720717
// ModifyNode applies the ConfigNode mod as a 'patch' to ConfigNode original, then returns the patched ConfigNode.
721718
// it uses FindConfigNodeIn(src, nodeType, nodeName, nodeTag) to recurse.
@@ -737,17 +734,10 @@ public static ConfigNode ModifyNode(NodeStack original, ConfigNode mod, PatchCon
737734

738735
Command cmd = CommandParser.Parse(modVal.name, out string valName);
739736

737+
Operator op = OperatorParser.Parse(valName, out valName);
738+
740739
if (cmd == Command.Special)
741740
{
742-
Match assignMatch = parseAssign.Match(valName);
743-
if (!assignMatch.Success)
744-
{
745-
context.progress.Error(context.patchUrl, "Error - Cannot parse value assigning command: " + valName);
746-
continue;
747-
}
748-
749-
valName = assignMatch.Groups[1].Value;
750-
751741
ConfigNode.Value val = RecurseVariableSearch(valName, nodeStack.Push(mod), context);
752742

753743
if (val == null)
@@ -756,30 +746,30 @@ public static ConfigNode ModifyNode(NodeStack original, ConfigNode mod, PatchCon
756746
continue;
757747
}
758748

759-
if (assignMatch.Groups[2].Success)
749+
if (op != Operator.Assign)
760750
{
761751
if (double.TryParse(modVal.value, NumberStyles.Float, CultureInfo.InvariantCulture.NumberFormat, out double s)
762752
&& double.TryParse(val.value, NumberStyles.Float, CultureInfo.InvariantCulture.NumberFormat, out double os))
763753
{
764-
switch (assignMatch.Groups[2].Value[0])
754+
switch (op)
765755
{
766-
case '*':
756+
case Operator.Multiply:
767757
val.value = (os * s).ToString(CultureInfo.InvariantCulture);
768758
break;
769759

770-
case '/':
760+
case Operator.Divide:
771761
val.value = (os / s).ToString(CultureInfo.InvariantCulture);
772762
break;
773763

774-
case '+':
764+
case Operator.Add:
775765
val.value = (os + s).ToString(CultureInfo.InvariantCulture);
776766
break;
777767

778-
case '-':
768+
case Operator.Subtract:
779769
val.value = (os - s).ToString(CultureInfo.InvariantCulture);
780770
break;
781771

782-
case '!':
772+
case Operator.Exponentiate:
783773
val.value = Math.Pow(os, s).ToString(CultureInfo.InvariantCulture);
784774
break;
785775
}
@@ -841,10 +831,6 @@ public static ConfigNode ModifyNode(NodeStack original, ConfigNode mod, PatchCon
841831
if (newNode.values[i].name == valName)
842832
valCount++;
843833

844-
char op = ' ';
845-
if (match.Groups[5].Success)
846-
op = match.Groups[5].Value[0];
847-
848834
string varValue;
849835
switch (cmd)
850836
{
@@ -1582,7 +1568,7 @@ private static string FindAndReplaceValue(
15821568
ref string valName,
15831569
string value,
15841570
ConfigNode newNode,
1585-
char op,
1571+
Operator op,
15861572
int index,
15871573
out ConfigNode.Value origVal,
15881574
PatchContext context,
@@ -1611,9 +1597,9 @@ private static string FindAndReplaceValue(
16111597
{
16121598
value = backupValue;
16131599
oValue = strArray[posIndex];
1614-
if (op != ' ')
1600+
if (op != Operator.Assign)
16151601
{
1616-
if (op == '^')
1602+
if (op == Operator.RegexReplace)
16171603
{
16181604
try
16191605
{
@@ -1643,23 +1629,23 @@ private static string FindAndReplaceValue(
16431629
{
16441630
switch (op)
16451631
{
1646-
case '*':
1632+
case Operator.Multiply:
16471633
value = (os * s).ToString(CultureInfo.InvariantCulture);
16481634
break;
16491635

1650-
case '/':
1636+
case Operator.Divide:
16511637
value = (os / s).ToString(CultureInfo.InvariantCulture);
16521638
break;
16531639

1654-
case '+':
1640+
case Operator.Add:
16551641
value = (os + s).ToString(CultureInfo.InvariantCulture);
16561642
break;
16571643

1658-
case '-':
1644+
case Operator.Subtract:
16591645
value = (os - s).ToString(CultureInfo.InvariantCulture);
16601646
break;
16611647

1662-
case '!':
1648+
case Operator.Exponentiate:
16631649
value = Math.Pow(os, s).ToString(CultureInfo.InvariantCulture);
16641650
break;
16651651
}

ModuleManager/ModuleManager.csproj

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,8 @@
5757
<Compile Include="ModuleManager.cs" />
5858
<Compile Include="ModListGenerator.cs" />
5959
<Compile Include="NeedsChecker.cs" />
60+
<Compile Include="Operator.cs" />
61+
<Compile Include="OperatorParser.cs" />
6062
<Compile Include="PatchApplier.cs" />
6163
<Compile Include="PatchContext.cs" />
6264
<Compile Include="PatchExtractor.cs" />

ModuleManager/Operator.cs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
using System;
2+
3+
namespace ModuleManager
4+
{
5+
public enum Operator
6+
{
7+
Assign,
8+
Add,
9+
Subtract,
10+
Multiply,
11+
Divide,
12+
Exponentiate,
13+
RegexReplace,
14+
}
15+
}

ModuleManager/OperatorParser.cs

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
using System;
2+
3+
namespace ModuleManager
4+
{
5+
public static class OperatorParser
6+
{
7+
public static Operator Parse(string name, out string valueName)
8+
{
9+
if (name == null) throw new ArgumentNullException(nameof(name));
10+
11+
if (name.Length == 0)
12+
{
13+
valueName = string.Empty;
14+
return Operator.Assign;
15+
}
16+
17+
Operator ret;
18+
switch (name[name.Length - 1])
19+
{
20+
case '+':
21+
ret = Operator.Add;
22+
break;
23+
24+
case '-':
25+
ret = Operator.Subtract;
26+
break;
27+
28+
case '*':
29+
ret = Operator.Multiply;
30+
break;
31+
32+
case '/':
33+
ret = Operator.Divide;
34+
break;
35+
36+
case '!':
37+
ret = Operator.Exponentiate;
38+
break;
39+
40+
case '^':
41+
ret = Operator.RegexReplace;
42+
break;
43+
44+
default:
45+
valueName = name;
46+
return Operator.Assign;
47+
}
48+
valueName = name.Substring(0, name.Length - 1).TrimEnd();
49+
return ret;
50+
}
51+
}
52+
}

ModuleManagerTests/ModuleManagerTests.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@
5959
<Compile Include="Logging\ExceptionMessageTest.cs" />
6060
<Compile Include="Logging\NormalMessageTest.cs" />
6161
<Compile Include="Logging\QueueLoggerTest.cs" />
62+
<Compile Include="OperatorParserTest.cs" />
6263
<Compile Include="PatchApplierTest.cs" />
6364
<Compile Include="PatchListTest.cs" />
6465
<Compile Include="Collections\ArrayEnumeratorTest.cs" />
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
using System;
2+
using Xunit;
3+
using ModuleManager;
4+
5+
namespace ModuleManagerTests
6+
{
7+
public class OperatorParserTest
8+
{
9+
[Fact]
10+
public void TestParse__Null()
11+
{
12+
ArgumentNullException ex = Assert.Throws<ArgumentNullException>(delegate
13+
{
14+
OperatorParser.Parse(null, out string _);
15+
});
16+
17+
Assert.Equal("name", ex.ParamName);
18+
}
19+
20+
[Fact]
21+
public void TestParse__Empty()
22+
{
23+
Operator op = OperatorParser.Parse("", out string result);
24+
25+
Assert.Equal(Operator.Assign, op);
26+
Assert.Equal("", result);
27+
}
28+
29+
[Fact]
30+
public void TestParse__Assign()
31+
{
32+
Operator op = OperatorParser.Parse("some_stuff,1[2, ]", out string result);
33+
34+
Assert.Equal(Operator.Assign, op);
35+
Assert.Equal("some_stuff,1[2, ]", result);
36+
}
37+
38+
[Fact]
39+
public void TestParse__Add()
40+
{
41+
Operator op = OperatorParser.Parse("some_stuff,1[2, ] +", out string result);
42+
43+
Assert.Equal(Operator.Add, op);
44+
Assert.Equal("some_stuff,1[2, ]", result);
45+
}
46+
47+
[Fact]
48+
public void TestParse__Subtract()
49+
{
50+
Operator op = OperatorParser.Parse("some_stuff,1[2, ] -", out string result);
51+
52+
Assert.Equal(Operator.Subtract, op);
53+
Assert.Equal("some_stuff,1[2, ]", result);
54+
}
55+
56+
[Fact]
57+
public void TestParse__Multiply()
58+
{
59+
Operator op = OperatorParser.Parse("some_stuff,1[2, ] *", out string result);
60+
61+
Assert.Equal(Operator.Multiply, op);
62+
Assert.Equal("some_stuff,1[2, ]", result);
63+
}
64+
65+
[Fact]
66+
public void TestParse__Divide()
67+
{
68+
Operator op = OperatorParser.Parse("some_stuff,1[2, ] /", out string result);
69+
70+
Assert.Equal(Operator.Divide, op);
71+
Assert.Equal("some_stuff,1[2, ]", result);
72+
}
73+
74+
[Fact]
75+
public void TestParse__Exponentiate()
76+
{
77+
Operator op = OperatorParser.Parse("some_stuff,1[2, ] !", out string result);
78+
79+
Assert.Equal(Operator.Exponentiate, op);
80+
Assert.Equal("some_stuff,1[2, ]", result);
81+
}
82+
83+
[Fact]
84+
public void TestParse__RegexReplace()
85+
{
86+
Operator op = OperatorParser.Parse("some_stuff,1[2, ] ^", out string result);
87+
88+
Assert.Equal(Operator.RegexReplace, op);
89+
Assert.Equal("some_stuff,1[2, ]", result);
90+
}
91+
}
92+
}

0 commit comments

Comments
 (0)