114 lines
3.2 KiB
C#
114 lines
3.2 KiB
C#
using System;
|
|
using System.Text.RegularExpressions;
|
|
using System.Collections.Generic;
|
|
|
|
namespace JDSongConverter
|
|
{
|
|
|
|
/// <summary>
|
|
/// Evaluate an expression containing text mixed with place holders.
|
|
/// </summary>
|
|
public class EvaluateExpression
|
|
{
|
|
|
|
private static Regex _regex = new Regex(@"\$\{(?<keyName>[\w]+)\}");
|
|
|
|
private MatchEvaluator _evaluator;
|
|
private Stack<string> _keysStack;
|
|
private IDictionary<string, string> _definitions;
|
|
|
|
|
|
#region Constructor
|
|
|
|
public EvaluateExpression(IDictionary<string, string> definitions)
|
|
{
|
|
_evaluator = new MatchEvaluator(Evaluator);
|
|
_keysStack = new Stack<string>();
|
|
_definitions = definitions;
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Public Methods
|
|
|
|
/// <summary>
|
|
/// Evaluate given expressions.
|
|
/// Need constant definition in parameter, and if used environment variable have to be
|
|
/// expanded.
|
|
/// </summary>
|
|
public static string Do(string expression, IDictionary<string, string> definitions, bool expandEnvironment = false)
|
|
{
|
|
if (string.IsNullOrEmpty(expression))
|
|
{
|
|
return expression;
|
|
}
|
|
|
|
EvaluateExpression context = new EvaluateExpression(definitions);
|
|
string evaluatedExpression = context.Recursive(expression);
|
|
|
|
return expandEnvironment ? Environment.ExpandEnvironmentVariables(evaluatedExpression) : evaluatedExpression;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Indicates an expression is fully evaluated.
|
|
/// </summary>
|
|
public static bool IsEvaluated(string expression)
|
|
{
|
|
if (string.IsNullOrEmpty(expression))
|
|
{
|
|
return true;
|
|
}
|
|
|
|
return !_regex.IsMatch(expression);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Private Methods
|
|
|
|
private string GetKeyName(Match match)
|
|
{
|
|
return (null != match) ? match.Groups["keyName"].Value : string.Empty;
|
|
}
|
|
|
|
private string Recursive(string expression)
|
|
{
|
|
try
|
|
{
|
|
Match match = _regex.Match(expression);
|
|
if (!match.Success)
|
|
{
|
|
return expression;
|
|
}
|
|
string evaluated = _regex.Replace(expression, _evaluator);
|
|
return (evaluated != expression) ? Recursive(evaluated) : evaluated;
|
|
}
|
|
catch (System.Exception ex)
|
|
{
|
|
throw new Exception("Impossible to evaluate : " + expression, ex);
|
|
}
|
|
}
|
|
|
|
private string Evaluator(Match match)
|
|
{
|
|
string keyName = GetKeyName(match);
|
|
string keyValue;
|
|
|
|
if (!_definitions.TryGetValue(keyName, out keyValue))
|
|
{
|
|
return match.Value;
|
|
}
|
|
if (_keysStack.Contains(keyName))
|
|
{
|
|
throw new Exception(keyName + " is used in a cyclic manner");
|
|
}
|
|
_keysStack.Push(keyName);
|
|
string expression = Recursive(keyValue);
|
|
_keysStack.Pop();
|
|
return expression;
|
|
}
|
|
|
|
#endregion
|
|
|
|
}
|
|
}
|