diff --git a/OpenRA.FileFormats/Evaluator.cs b/OpenRA.FileFormats/Evaluator.cs new file mode 100644 index 0000000000..4cec92809a --- /dev/null +++ b/OpenRA.FileFormats/Evaluator.cs @@ -0,0 +1,93 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +namespace OpenRA.FileFormats +{ + public static class Evaluator + { + public static int Evaluate(string expr) + { + return Evaluate(expr, new Dictionary()); + } + + public static int Evaluate(string expr, Dictionary syms) + { + var toks = Tokens(expr, "+-*/()"); + var postfix = ToPostfix(toks, syms); + + var s = new Stack(); + + foreach (var t in postfix) + { + switch (t[0]) + { + case '+': ApplyBinop(s, (x, y) => x + y); break; + case '-': ApplyBinop(s, (x, y) => x - y); break; + case '*': ApplyBinop(s, (x, y) => x * y); break; + case '/': ApplyBinop(s, (x, y) => x / y); break; + default: s.Push(int.Parse(t)); break; + } + } + + return s.Pop(); + } + + static void ApplyBinop( Stack s, Func f ) + { + var x = s.Pop(); + var y = s.Pop(); + s.Push( f(x,y) ); + } + + static IEnumerable ToPostfix(IEnumerable toks, Dictionary syms) + { + var s = new Stack(); + + foreach (var t in toks) + { + if (t[0] == '(') s.Push(t); + else if (t[0] == ')') + { + var temp = ""; + while ((temp = s.Pop()) != "(") yield return temp; + } + else if (char.IsNumber(t[0])) yield return t; + else if (char.IsLetter(t[0])) yield return syms[t].ToString(); + else + { + while (s.Count > 0 && Prec[t] <= Prec[s.Peek()]) yield return s.Pop(); + s.Push(t); + } + } + + while (s.Count > 0) yield return s.Pop(); + } + + static readonly Dictionary Prec + = new Dictionary { { "+", 0 }, { "-", 0 }, { "*", 1 }, { "/", 1 } }; + + static IEnumerable Tokens(string expr, string ops) + { + var s = ""; + foreach (var c in expr) + { + if (char.IsWhiteSpace(c)) + { + if (s != "") yield return s; + s = ""; + } + else if (ops.Contains(c)) + { + if (s != "") yield return s; + s = ""; + yield return "" + c; + } + else + s += c; + } + + if (s != "") yield return s; + } + } +} diff --git a/OpenRA.FileFormats/OpenRA.FileFormats.csproj b/OpenRA.FileFormats/OpenRA.FileFormats.csproj index 174eb124e5..22932f3639 100644 --- a/OpenRA.FileFormats/OpenRA.FileFormats.csproj +++ b/OpenRA.FileFormats/OpenRA.FileFormats.csproj @@ -56,6 +56,7 @@ +