mirror of
https://github.com/Stone-Red-Code/YesNt-Interpreter.git
synced 2026-09-04 09:06:41 +02:00
190 lines
5.8 KiB
C#
190 lines
5.8 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Text;
|
|
using System.Text.RegularExpressions;
|
|
|
|
using YesNt.Interpreter.Runtime;
|
|
|
|
namespace YesNt.Interpreter.Utilities;
|
|
|
|
/// <summary>
|
|
/// Provides high-performance template substitution for variables and stack parameters.
|
|
/// </summary>
|
|
internal static class TemplateProcessor
|
|
{
|
|
/// <summary>
|
|
/// Replaces all occurrences of ${variableName} with their current values.
|
|
/// </summary>
|
|
public static string ProcessVariables(string input, RuntimeInformation runtimeInfo)
|
|
{
|
|
if (string.IsNullOrEmpty(input))
|
|
{
|
|
return input;
|
|
}
|
|
|
|
int startIdx = input.IndexOf("${", StringComparison.Ordinal);
|
|
if (startIdx == -1)
|
|
{
|
|
return input;
|
|
}
|
|
|
|
StringBuilder sb = new StringBuilder(input.Length);
|
|
int lastIdx = 0;
|
|
|
|
while (startIdx != -1)
|
|
{
|
|
_ = sb.Append(input, lastIdx, startIdx - lastIdx);
|
|
int endIdx = input.IndexOf('}', startIdx + 2);
|
|
if (endIdx == -1)
|
|
{
|
|
_ = sb.Append("${");
|
|
lastIdx = startIdx + 2;
|
|
}
|
|
else
|
|
{
|
|
string varName = input[(startIdx + 2)..endIdx];
|
|
if (runtimeInfo.Variables.TryGetValue(varName, out string value))
|
|
{
|
|
_ = sb.Append(value);
|
|
}
|
|
else if (runtimeInfo.GlobalVariables.TryGetValue(varName, out value))
|
|
{
|
|
_ = sb.Append(value);
|
|
}
|
|
else if (!runtimeInfo.IsSearching)
|
|
{
|
|
runtimeInfo.Exit(ExitMessages.VariableNotFound(varName), true);
|
|
return input;
|
|
}
|
|
else
|
|
{
|
|
_ = sb.Append("${");
|
|
_ = sb.Append(varName);
|
|
_ = sb.Append('}');
|
|
}
|
|
|
|
lastIdx = endIdx + 1;
|
|
}
|
|
|
|
startIdx = input.IndexOf("${", lastIdx, StringComparison.Ordinal);
|
|
}
|
|
|
|
_ = sb.Append(input, lastIdx, input.Length - lastIdx);
|
|
return sb.ToString();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Replaces all occurrences of a placeholder (e.g., %in, %out) with values popped from a stack.
|
|
/// </summary>
|
|
public static string ProcessStackParameters(string input, string placeholder, Stack<string> stack, RuntimeInformation runtimeInfo, string emptyStackMessage)
|
|
{
|
|
if (string.IsNullOrEmpty(input))
|
|
{
|
|
return input;
|
|
}
|
|
|
|
int startIdx = input.IndexOf(placeholder, StringComparison.Ordinal);
|
|
if (startIdx == -1)
|
|
{
|
|
return input;
|
|
}
|
|
|
|
StringBuilder sb = new StringBuilder(input.Length);
|
|
int lastIdx = 0;
|
|
int placeholderLen = placeholder.Length;
|
|
|
|
while (startIdx != -1)
|
|
{
|
|
_ = sb.Append(input, lastIdx, startIdx - lastIdx);
|
|
if (stack.Count == 0)
|
|
{
|
|
runtimeInfo.Exit(emptyStackMessage, true);
|
|
return input;
|
|
}
|
|
_ = sb.Append(stack.Pop());
|
|
lastIdx = startIdx + placeholderLen;
|
|
startIdx = input.IndexOf(placeholder, lastIdx, StringComparison.Ordinal);
|
|
}
|
|
|
|
_ = sb.Append(input, lastIdx, input.Length - lastIdx);
|
|
return sb.ToString();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Replaces all occurrences of a placeholder with a fixed value.
|
|
/// </summary>
|
|
public static string ProcessSimplePlaceholders(string input, string placeholder, string value)
|
|
{
|
|
return string.IsNullOrEmpty(input) ? input : input.Replace(placeholder, value, StringComparison.Ordinal);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Replaces all occurrences of a placeholder with values generated by a provider function.
|
|
/// </summary>
|
|
public static string ProcessDynamicPlaceholders(string input, string placeholder, Func<string> valueProvider)
|
|
{
|
|
if (string.IsNullOrEmpty(input))
|
|
{
|
|
return input;
|
|
}
|
|
|
|
int startIdx = input.IndexOf(placeholder, StringComparison.Ordinal);
|
|
if (startIdx == -1)
|
|
{
|
|
return input;
|
|
}
|
|
|
|
StringBuilder sb = new StringBuilder(input.Length);
|
|
int lastIdx = 0;
|
|
int placeholderLen = placeholder.Length;
|
|
|
|
while (startIdx != -1)
|
|
{
|
|
_ = sb.Append(input, lastIdx, startIdx - lastIdx);
|
|
_ = sb.Append(valueProvider());
|
|
lastIdx = startIdx + placeholderLen;
|
|
startIdx = input.IndexOf(placeholder, lastIdx, StringComparison.Ordinal);
|
|
}
|
|
|
|
_ = sb.Append(input, lastIdx, input.Length - lastIdx);
|
|
return sb.ToString();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Replaces all occurrences of arithmetic expressions with their results.
|
|
/// </summary>
|
|
public static string ProcessCalculations(string input, RuntimeInformation runtimeInfo, Regex calculationRegex)
|
|
{
|
|
if (string.IsNullOrEmpty(input))
|
|
{
|
|
return input;
|
|
}
|
|
|
|
MatchCollection matches = calculationRegex.Matches(input);
|
|
if (matches.Count == 0)
|
|
{
|
|
return input;
|
|
}
|
|
|
|
StringBuilder sb = new StringBuilder(input.Length);
|
|
int lastIdx = 0;
|
|
|
|
for (int i = 0; i < matches.Count; i++)
|
|
{
|
|
Match match = matches[i];
|
|
_ = sb.Append(input, lastIdx, match.Index - lastIdx);
|
|
|
|
string res = Evaluator.Calculate(match.Value);
|
|
if (res is null)
|
|
{
|
|
runtimeInfo.Exit(ExitMessages.InvalidOperation, true);
|
|
return input;
|
|
}
|
|
_ = sb.Append(res);
|
|
lastIdx = match.Index + match.Length;
|
|
}
|
|
|
|
_ = sb.Append(input, lastIdx, input.Length - lastIdx);
|
|
return sb.ToString();
|
|
}
|
|
} |