2023-09-24 18:51:23 -07:00
|
|
|
using System.Text.RegularExpressions;
|
|
|
|
|
|
|
|
namespace SupaLidlGame.Debug;
|
|
|
|
|
|
|
|
public static class Sanitizer
|
|
|
|
{
|
|
|
|
private static Regex _nonAlphanum = new("[^a-zA-Z0-9_]");
|
|
|
|
|
2023-09-26 10:23:04 -07:00
|
|
|
private static Regex _nonNodeName = new("[^a-zA-Z0-9_\\-\\/\\.\\:]");
|
2023-09-24 18:51:23 -07:00
|
|
|
|
|
|
|
private static string ScanString(CharIterator iterator)
|
|
|
|
{
|
|
|
|
string ret = "";
|
|
|
|
|
|
|
|
while (iterator.GetNext() != '\0')
|
|
|
|
{
|
|
|
|
char c = iterator.MoveNext();
|
|
|
|
|
|
|
|
if (c == '"')
|
|
|
|
{
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
else if (c == '\\')
|
|
|
|
{
|
|
|
|
char escape = iterator.MoveNext();
|
|
|
|
|
|
|
|
switch (escape)
|
|
|
|
{
|
|
|
|
case 'n':
|
|
|
|
ret += '\n';
|
|
|
|
break;
|
|
|
|
case 't':
|
|
|
|
ret += '\t';
|
|
|
|
break;
|
|
|
|
case '\0':
|
|
|
|
throw new InterpreterException("Unexpected EOL",
|
|
|
|
iterator.Line, iterator.Column); default:
|
|
|
|
ret += escape;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ret += c;
|
|
|
|
}
|
|
|
|
throw new InterpreterException("Unexpected EOL, expected '\"'",
|
|
|
|
iterator.Line, iterator.Column);
|
|
|
|
}
|
|
|
|
|
|
|
|
private static string ScanNodePath(CharIterator iterator)
|
|
|
|
{
|
|
|
|
string ret = "";
|
|
|
|
while (iterator.GetNext() != '\0')
|
|
|
|
{
|
|
|
|
char c = iterator.MoveNext();
|
|
|
|
|
|
|
|
if (c == '"')
|
|
|
|
{
|
|
|
|
return ScanString(iterator);
|
|
|
|
}
|
|
|
|
else if (_nonNodeName.IsMatch(c.ToString()))
|
|
|
|
{
|
|
|
|
iterator.MoveBack();
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret += c;
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2023-09-26 10:23:04 -07:00
|
|
|
private static string ScanUntilOrEOL(CharIterator iterator, char? delim)
|
2023-09-24 18:51:23 -07:00
|
|
|
{
|
|
|
|
string ret = "";
|
|
|
|
while (iterator.GetNext() != '\0')
|
|
|
|
{
|
2023-09-26 10:23:04 -07:00
|
|
|
char c = iterator.MoveNext();
|
2023-09-24 18:51:23 -07:00
|
|
|
if (c == delim)
|
|
|
|
{
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
ret += c;
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
private static string ScanGlobalCommand(CharIterator iterator)
|
|
|
|
{
|
|
|
|
string ret = "";
|
|
|
|
while (iterator.GetNext() != '\0')
|
|
|
|
{
|
|
|
|
char c = iterator.MoveNext();
|
|
|
|
if (_nonAlphanum.IsMatch(c.ToString()))
|
|
|
|
{
|
|
|
|
iterator.MoveBack();
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
ret += c;
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
public static string Sanitize(string input)
|
|
|
|
{
|
|
|
|
CharIterator iterator = new(input);
|
|
|
|
string ret = "";
|
|
|
|
|
|
|
|
while (iterator.GetNext() != '\0')
|
|
|
|
{
|
|
|
|
char c = iterator.MoveNext();
|
|
|
|
|
|
|
|
if (c == '$')
|
|
|
|
{
|
|
|
|
string nodePath = ScanNodePath(iterator);
|
|
|
|
ret += $"from.call(\"{nodePath}\")";
|
|
|
|
}
|
|
|
|
else if (c == '"')
|
|
|
|
{
|
|
|
|
string str = ScanString(iterator);
|
|
|
|
ret += $"\"{str}\"";
|
|
|
|
}
|
|
|
|
else if (c == '\\')
|
|
|
|
{
|
|
|
|
// \global -> global.call
|
|
|
|
string command = ScanGlobalCommand(iterator);
|
|
|
|
ret += $"{command}.call";
|
|
|
|
}
|
2023-09-26 10:23:04 -07:00
|
|
|
else if (c == '=')
|
|
|
|
{
|
|
|
|
if (iterator.GetNext(-2) != '!')
|
|
|
|
{
|
|
|
|
var val = ScanUntilOrEOL(iterator, null);
|
|
|
|
ret = ret.Replace("from.call", "to_node_path.call");
|
|
|
|
ret = $"set_prop.call({ret}, {val})";
|
|
|
|
}
|
|
|
|
}
|
2023-09-24 18:51:23 -07:00
|
|
|
else
|
|
|
|
{
|
|
|
|
ret += c;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
}
|