Skip to content

Commit 3e24b5f

Browse files
verify value expressions in strings on compilation
1 parent 0cf15fc commit 3e24b5f

5 files changed

Lines changed: 53 additions & 18 deletions

File tree

Code/TokenSystem/Tokens/ValueTokens/TextToken.cs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,18 @@ protected override IParseResult InternalParse(Script scr)
1414
{
1515
return new Ignore();
1616
}
17-
17+
18+
if (!TextValue.HasExpression(Slice.Value))
19+
{
20+
Value = new StaticTextValue(Slice.Value);
21+
return new Success();
22+
}
23+
24+
if (TextValue.Lint(Slice.Value, scr).HasErrored(out var error))
25+
{
26+
return new Error(error);
27+
}
28+
1829
Value = new DynamicTextValue(Slice.Value, scr);
1930
return new Success();
2031
}

Code/ValueSystem/LiteralValue.cs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,12 @@ public abstract class LiteralValue : Value
1212

1313
private static Type[]? _subclasses;
1414
public static Type[] Subclasses => _subclasses ??= typeof(LiteralValue).Assembly.GetTypes()
15-
.Where(t => t.IsClass && t is { IsAbstract: false, IsGenericTypeDefinition: false } && typeof(LiteralValue).IsAssignableFrom(t) && typeof(IValueWithProperties).IsAssignableFrom(t))
15+
.Where(t =>
16+
t.IsClass
17+
&& t is { IsAbstract: false, IsGenericTypeDefinition: false }
18+
&& typeof(LiteralValue).IsAssignableFrom(t)
19+
&& typeof(IValueWithProperties).IsAssignableFrom(t)
20+
)
1621
.ToArray();
1722

1823
/// <summary>

Code/ValueSystem/TextValue.cs

Lines changed: 31 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -37,37 +37,56 @@ public static implicit operator string(TextValue value)
3737

3838
[UsedImplicitly]
3939
public new static string FriendlyName = "text value";
40-
41-
public static string ParseValue(string text, Script script) => ExpressionRegex.Replace(text, match =>
40+
41+
public static TryGet<ExpressionToken?> ParseExpression(string text, Script script)
4242
{
43-
if (match.Value.StartsWith("~")) return match.Value[1..];
43+
if (text.StartsWith("~")) return null as ExpressionToken;
4444

45-
if (Tokenizer.SliceLine(match.Value).HasErrored(out var error, out var slices))
45+
if (Tokenizer.SliceLine(text).HasErrored(out var error, out var enumSlices))
4646
{
47-
Log.ScriptWarn(script, error);
48-
return "<error>";
47+
return error;
4948
}
5049

51-
if (slices.FirstOrDefault() is not CollectionSlice { Type: CollectionBrackets.Curly } collection)
50+
if (enumSlices.ToArray() is not [CollectionSlice { Type: CollectionBrackets.Curly } collection])
5251
{
53-
throw new AndrzejFuckedUpException();
52+
return "Parsing failed";
5453
}
5554

5655
// ReSharper disable once DuplicatedSequentialIfBodies
5756
if (ExpressionToken.TryParse(collection, script).HasErrored(out error, out var token))
5857
{
59-
Log.ScriptWarn(script, error);
60-
return "<error>";
58+
return error;
6159
}
6260

63-
if (((BaseToken)token).TryGet<LiteralValue>().HasErrored(out error, out var value))
61+
return token;
62+
}
63+
64+
public static bool HasExpression(string text) => ExpressionRegex.IsMatch(text);
65+
66+
public static string ParseValue(string text, Script script) => ExpressionRegex.Replace(text, match =>
67+
{
68+
if (ParseExpression(match.Value, script).HasErrored(out var error, out var token)
69+
|| ((BaseToken)token).TryGet<LiteralValue>().HasErrored(out error, out var value))
6470
{
6571
Log.ScriptWarn(script, error);
6672
return "<error>";
6773
}
68-
74+
6975
return value.StringRep;
7076
});
77+
78+
public static Result Lint(string text, Script script)
79+
{
80+
foreach (var match in ExpressionRegex.Matches(text).Cast<Match>())
81+
{
82+
if (ParseExpression(match.Value, script).HasErrored(out var error, out var token))
83+
{
84+
return error;
85+
}
86+
}
87+
88+
return true;
89+
}
7190

7291
private class Prop<T>(Func<TextValue, T> handler, string? description)
7392
: IValueWithProperties.PropInfo<TextValue, T>(handler, description) where T : Value;

Example Scripts/chaosCoin.ser

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -178,10 +178,10 @@ if $effect is 9
178178

179179
# we can teleport @swapPlayer directly to @evPlayer
180180
TPPlayer @swapPlayer @evPlayer
181-
Broadcast @swapPlayer 5s "{$baseText}You have swapped places with {@evPlayer name}"
181+
Broadcast @swapPlayer 5s "{$baseText}You have swapped places with {@evPlayer -> name}"
182182

183183
# because @swapPlayer is in the same place as @evPlayer, we need to use the saved values to teleport
184184
TPPosition @evPlayer $swapX $swapY $swapZ
185-
Broadcast @evPlayer 5s "{$baseText}You have swapped places with {@swapPlayer name}"
185+
Broadcast @evPlayer 5s "{$baseText}You have swapped places with {@swapPlayer -> name}"
186186
stop
187187
end

Example Scripts/killStreak.ser

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,9 @@ if {VarExists @evAttacker} is true
1313

1414
# announce milestone
1515
if $new is 5
16-
Broadcast @all 5s "{@evAttacker name} is on a KILLING SPREE (5 Kills)!"
16+
Broadcast @all 5s "{@evAttacker -> name} is on a KILLING SPREE (5 Kills)!"
1717
elif $new is 10
18-
Broadcast @all 5s "{@evAttacker name} is UNSTOPPABLE (10 Kills)!"
18+
Broadcast @all 5s "{@evAttacker -> name} is UNSTOPPABLE (10 Kills)!"
1919
end
2020
end
2121

0 commit comments

Comments
 (0)