added Evaluator.cs
This commit is contained in:
93
OpenRA.FileFormats/Evaluator.cs
Normal file
93
OpenRA.FileFormats/Evaluator.cs
Normal file
@@ -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<string, int>());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int Evaluate(string expr, Dictionary<string, int> syms)
|
||||||
|
{
|
||||||
|
var toks = Tokens(expr, "+-*/()");
|
||||||
|
var postfix = ToPostfix(toks, syms);
|
||||||
|
|
||||||
|
var s = new Stack<int>();
|
||||||
|
|
||||||
|
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<int> s, Func<int,int,int> f )
|
||||||
|
{
|
||||||
|
var x = s.Pop();
|
||||||
|
var y = s.Pop();
|
||||||
|
s.Push( f(x,y) );
|
||||||
|
}
|
||||||
|
|
||||||
|
static IEnumerable<string> ToPostfix(IEnumerable<string> toks, Dictionary<string, int> syms)
|
||||||
|
{
|
||||||
|
var s = new Stack<string>();
|
||||||
|
|
||||||
|
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<string, int> Prec
|
||||||
|
= new Dictionary<string, int> { { "+", 0 }, { "-", 0 }, { "*", 1 }, { "/", 1 } };
|
||||||
|
|
||||||
|
static IEnumerable<string> 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -56,6 +56,7 @@
|
|||||||
<Compile Include="Collections\Set.cs" />
|
<Compile Include="Collections\Set.cs" />
|
||||||
<Compile Include="DisposableAction.cs" />
|
<Compile Include="DisposableAction.cs" />
|
||||||
<Compile Include="Dune2ShpReader.cs" />
|
<Compile Include="Dune2ShpReader.cs" />
|
||||||
|
<Compile Include="Evaluator.cs" />
|
||||||
<Compile Include="Exts.cs" />
|
<Compile Include="Exts.cs" />
|
||||||
<Compile Include="FieldLoader.cs" />
|
<Compile Include="FieldLoader.cs" />
|
||||||
<Compile Include="FileSystem.cs" />
|
<Compile Include="FileSystem.cs" />
|
||||||
|
|||||||
Reference in New Issue
Block a user