1.代碼
using Spring.Expressions;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
namespace ConsoleApplication49
{
public interface IExpressionContext
{
/// <summary>
/// 什麼是終結符單詞 用戶端自己要給出
/// </summary>
Dictionary<string, string> map { get; set; }
string GetValueByKey(string key);
}
public class ExpressionContext : IExpressionContext
{
public Dictionary<string, string> map { get; set; }
public string GetValueByKey(string key)
{
if (map.ContainsKey(key))
return map[key];
return key;
}
}
public abstract class Expression
{
/// <summary>
/// 終結符
/// </summary>
private string key;
public string Key
{
get
{
return key;
}
set
{
key = value;
}
}
//解析公式和數值,其中var中的key值是是公式中的參數,value值是具體的數字
//這裡字典可以抽象為上下文 ctx,此處自己擴充
public abstract string interpreter(IExpressionContext ctx);
}
public class VarExpression : Expression
{
public VarExpression(string _key)
{
this.Key = _key;
}
//從map中取之
public override string interpreter(IExpressionContext ctx)
{
if (ctx.map.ContainsKey(Key))
return ctx.GetValueByKey(Key);
else if (Key.IndexOf('(') >= 0)
{
var key1 = Key.Split('(')[1];
return "(" + ctx.GetValueByKey(key1);
}
else if (Key.IndexOf(')') >= 0)
{
var key1 = Key.Split(')')[0];
return ctx.GetValueByKey(key1) + ")";
}
return Key;
}
}
public abstract class SymbolExpression : Expression
{
protected Expression left;
protected Expression right;
//所有的解析公式都應隻關心自己左右兩個表達式的結果
public SymbolExpression(Expression _left, Expression _right)
{
this.left = _left;
this.right = _right;
}
}
public class AddExpression : SymbolExpression
{
public AddExpression(Expression _left, Expression _right) : base(_left, _right)
{
}
//把左右兩個表達式運算的結果加起來
public override string interpreter(IExpressionContext ctx)
{
return (base.left.interpreter(ctx)) + "+" + (base.right.interpreter(ctx));
}
}
public class SubExpression : SymbolExpression
{
public SubExpression(Expression _left, Expression _right) : base(_left, _right)
{
}
//左右兩個表達式相減
public override string interpreter(IExpressionContext ctx)
{
return base.left.interpreter(ctx) + "-" + base.right.interpreter(ctx);
}
}
public class MultExpression : SymbolExpression
{
public MultExpression(Expression _left, Expression _right) : base(_left, _right)
{
}
//左右兩個表達式相減
public override string interpreter(IExpressionContext ctx)
{
return base.left.interpreter(ctx) + "*" + base.right.interpreter(ctx);
}
}
public class Dividexpression : SymbolExpression
{
public Dividexpression(Expression _left, Expression _right) : base(_left, _right)
{
}
//左右兩個表達式相減
public override string interpreter(IExpressionContext ctx)
{
return base.left.interpreter(ctx) + "/" + base.right.interpreter(ctx);
}
}
public class PExpression : SymbolExpression
{
public PExpression(Expression _left, Expression _right) : base(_left, _right)
{
}
//左右兩個表達式相減
public override string interpreter(IExpressionContext ctx)
{
return base.left.interpreter(ctx) + "^" + base.right.interpreter(ctx);
}
}
public class Calculator
{
//定義的表達式
private Expression expression;
//構造函數傳參,并解析
public Calculator(string exprStr)
{
//定義一個堆棧,安排運算的先後順序
Stack<Expression> stack = new Stack<Expression>();
string[] sb = { "+", "-", "*", "/", "^" };
List<string> items = new List<string>();
string word = string.Empty;
char[] chs = exprStr.ToCharArray();
List<string> chsdict = new List<string>();
foreach (var item in chs)
{
chsdict.Add(item.ToString());
}
foreach (string ch in chsdict)
{
if (!sb.Contains(ch.ToString()))
{
word += ch.ToString();
//if (exprStr.IndexOf(ch) == exprStr.ToCharArray().Length - 1)
if (object.ReferenceEquals(ch, chsdict[chsdict.Count - 1]))
{
items.Add(word);
}
}
else
{
items.Add(word.Clone().ToString());
items.Add(ch.ToString());
word = string.Empty;
}
}
int cx = 0;
//表達式拆分為字元數組
char[] charArray = exprStr.ToCharArray();
//運算
Expression left = null;
Expression right = null;
for (int i = 0; i < items.Count; i++)
{
if (cx >= items.Count)
{
break;
}
word = items[cx++];
switch (word)
{
case "+": //加法
//加法結果放到堆棧中
left = stack.Peek();
right = new VarExpression(items[cx++]);
stack.Push(new AddExpression(left, right));
break;
case "-":
left = stack.Peek();
right = new VarExpression(items[cx++]);
stack.Push(new SubExpression(left, right));
break;
case "^":
left = stack.Peek();
right = new VarExpression(items[cx++]);
stack.Push(new PExpression(left, right));
break;
case "/":
left = stack.Peek();
right = new VarExpression(items[cx++]);
stack.Push(new Dividexpression(left, right));
break;
case "*":
left = stack.Peek();
right = new VarExpression(items[cx++]);
stack.Push(new MultExpression(left, right));
break;
default: //公式中的變量
stack.Push(new VarExpression(word));
break;
}
}
//把運算結果抛出來
this.expression = stack.Peek();
}
//開始運算
public string run(IExpressionContext ctx)
{
return this.expression.interpreter(ctx);
}
}
public class Client
{
//運作四則運算
public static void Main(string[] args)
{
while (true)
{
string exp = string.Empty;
string expStr = getExpStr();
//指派 得到終結符單詞
Dictionary<string, string> maps = getValue(expStr);
Calculator cal = new Calculator(expStr);
IExpressionContext ctx = new ExpressionContext();
ctx.map = maps;
exp = cal.run(ctx);
var val = ExpressionEvaluator.GetValue(null, exp);
Console.WriteLine("運算結果為:" + expStr + "=" + exp + "=" + val.ToString());
}
Console.ReadKey();
}
//獲得表達式
public static String getExpStr()
{
Console.WriteLine("請輸入表達式:");
return Console.ReadLine();
}
//獲得值映射 什麼才是終結符單詞用戶端要自己給出定義
public static Dictionary<string, string> getValue(string exprStr)
{
exprStr = exprStr.Replace("(", "").Replace(")", "");
//定義非終結符
string[] sb = { "+", "-", "*", "/", "^" };
string copyExpStr = exprStr.Clone().ToString();
foreach (char ch in exprStr.ToCharArray())
{
if (sb.Contains(ch.ToString()))
{
copyExpStr = copyExpStr.Replace(ch.ToString(), ",");
}
}
var items = copyExpStr.Split(',');
Dictionary<string, string> map = new Dictionary<string, string>();
//解析有幾個參數要傳遞
foreach (string ch in items)
{
if (!sb.Contains(ch.ToString()) && !Regex.IsMatch(ch, @"[0-9]+(.d+)?") && ch != "(" && ch != ")")
{
//解決重複參數的問題
if (!map.ContainsKey(ch.ToString()))
{
Console.WriteLine("請輸入" + ch + "的值:");
string in1 = Console.ReadLine();
map.Add(ch.ToString(), in1);
}
}
}
return map;
}
}
}
2.用戶端測試

轉載于:https://www.cnblogs.com/kexb/p/6262132.html