表达式计算
来源:互联网 发布:伴奏软件免费下载 编辑:程序博客网 时间:2024/05/21 06:02
自定义表达式解析,涉及到三个主要步骤:
1.关键字析取
2.中序表达式转逆波兰表达式
3.逆波兰表达式运算。
下面给出一个示例,整个编码过程,在支持运算符有限的情况下,大约一天即可完成(C#实现),这个实现中涉及到的比较好的实现方式有两点:
1.我们生成了一个逆波兰式的中间结果,这个结果是对象化的。
2.支持中序表达式中函数的析取和逆波兰式运算时的函数扩展。
首先是调用代码:
//表达式运算示例 private void button1_Click(object sender, EventArgs e) { List<rpn.rpngenerator.op></rpn.rpngenerator.op> ops = rpn.RpnGenerator.GetCommonOps(); List<rpn.rpngenerator.item></rpn.rpngenerator.item> mn = rpn.RpnAnalyser.GetMn(this.textBox1.Text, ref ops); List<rpn.rpngenerator.item></rpn.rpngenerator.item> rpn1 = rpn.RpnGenerator.GetRpnFromMn(mn); String s = ""; foreach (rpn.RpnGenerator.ITEM i in rpn1) { s += i.value; s += " "; } this.textBox2.Text = s; MyRpnCalc rc = new MyRpnCalc(); textBox3.Text = rc.Calc(rpn1).value; } //逆波兰运算重载 class MyRpnCalc : rpn.RpnCalc { public override RpnGenerator.Data CalcOp(RpnGenerator.Op op, ref List<rpngenerator.data></rpngenerator.data> result) { RpnGenerator.Data d = new RpnGenerator.Data(""); switch (op.value) { case "or": { RpnGenerator.Data rhs2 = result.Last(); result.RemoveAt(result.Count - 1); RpnGenerator.Data rhs1 = result.Last(); result.RemoveAt(result.Count - 1); bool l1; bool l2; l1 = bool.Parse(rhs1.value); l2 = bool.Parse(rhs2.value); d.value = (l1 || l2).ToString(); } break; default: return base.CalcOp(op, ref result); } return d; } } }
上面的代码中处理了函数的解析,所以涉及到一个重载函数的定义,其中“or(x,y)”即是一个扩展出的自定义函数,接下来是主体部分:
/* * rpn.cs * * 逆波兰表达式运算辅助函数族。本实现仅对逻辑和比较运算符进行解析,仅供参考。 * * 内含: * 1. 表达式析取(包含函数的自动解析、空白字符处理) * 2. 中序表达式转逆波兰表达式 * 3. 部分逻辑运算的实现 * * last edition: Aug28,2017 * first edition: Aug25,2017 * author: fengxh */using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;namespace rpn{ /// <summary> /// 表达式析取 /// </summary> public class RpnAnalyser { /// <summary> /// 完整功能的表达式析取函数 /// </summary> /// 待解析的中序表达式<param></param> /// 运算符集合,不应包含函数<param></param> /// <returns>可供逆波兰转换的表达式</returns> public static List<rpngenerator.item></rpngenerator.item> GetMn(String s, ref List<rpngenerator.op></rpngenerator.op> ops) { List<rpngenerator.item></rpngenerator.item> l = new List<rpngenerator.item></rpngenerator.item>(); string cur = ""; int leftMatchCnt = 0; int rightMatchLength = 0; while (s.Length != 0) { cur += s[0]; s = s.Substring(1); RECHECK: rightMatchLength = 0; int oldLeftMatchCnt = leftMatchCnt; leftMatchCnt = 0; foreach (RpnGenerator.Op op in ops) { if (op.value.Length >= cur.Length && op.value.Substring(0, cur.Length) == cur) leftMatchCnt++; if (cur.Length >= op.value.Length) { if (cur.Substring(cur.Length - op.value.Length, op.value.Length) == op.value) { rightMatchLength = op.value.Length; } } } if (leftMatchCnt == 1) { foreach (RpnGenerator.Op op in ops) { if (op.value == cur) { if (op.value == "(") { if (l.Count > 0 && (l.Last().GetType() != typeof(RpnGenerator.Op))) { RpnGenerator.Op o = new RpnGenerator.Op(l.Last().value, -1, 99); l.RemoveAt(l.Count() - 1); l.Add(o); ops.Add((RpnGenerator.Op)o.Clone()); } } l.Add((RpnGenerator.Op)op.Clone()); leftMatchCnt = 0; break; } } if (leftMatchCnt == 0) { cur = ""; } leftMatchCnt = 0; } else if (rightMatchLength > 0 && leftMatchCnt == 0 && oldLeftMatchCnt == 0) { RpnGenerator.Data d = new RpnGenerator.Data(cur.Substring(0, cur.Length - rightMatchLength)); cur = cur.Substring(d.value.Length, cur.Length - d.value.Length); d.value = d.value.Trim(); if (d.value.Length > 0) { l.Add(d); } leftMatchCnt = 0; if (cur.Length > 0) goto RECHECK; } else if (oldLeftMatchCnt > 0 && leftMatchCnt == 0) { foreach (RpnGenerator.Op op in ops) { if (op.value.Length == cur.Length - 1 && cur.Substring(0, op.value.Length) == op.value) { l.Add((RpnGenerator.Op)op.Clone()); cur = cur.Substring(op.value.Length, cur.Length - op.value.Length); leftMatchCnt = 0; goto RECHECK; } } } } if (cur.Length != 0) { RpnGenerator.Data d = new RpnGenerator.Data(cur.Trim()); if (d.value.Length > 0) { l.Add(d); } } return l; } } /// <summary> /// 中序->逆波兰转换 /// 本模块的输入是结构化处理过的表达式,其基本元素是RpnGenerator.ITEM /// </summary> public class RpnGenerator { /// <summary> /// 表达式基本元素 /// </summary> public class ITEM { public string value; public ITEM(string value) { this.value = value; } } /// <summary> /// 操作数 /// </summary> public class Data : ITEM { public Data(string value) : base(value) { } } /// <summary> /// 运算符 /// </summary> public class Op : ITEM, ICloneable { public Op(string value) : base(value) { this.cntOfData = 0; this.priority = 0; } public Op(string value, int cntOfData, int priority) :base (value) { this.cntOfData = cntOfData; this.priority = priority; } public Object Clone() { return new Op(this.value, this.cntOfData, this.priority); } bool isOperator1() { return cntOfData == 1; } bool isOperator2() { return cntOfData == 2; } bool isFunction() { return cntOfData == -1; } public int cntOfData; public int priority; } /// <summary> /// 返回内置运算符集合 /// </summary> /// <returns>内置运算符集合</returns> public static List<op></op> GetCommonOps() { List<op></op> l = new List<op></op>(); l.AddRange(new Op[] { Op_equal, //Op_lastOp, Op_leftBracket, Op_logic_and, Op_comma, Op_greater, Op_greaterOrEqual, Op_isEqual, Op_less, Op_lessOrEqual, Op_logic_not, Op_notEqual, Op_logic_or, Op_RightBracket }); return l; } static public Op Op_lastOp = new Op("#"); static public Op Op_leftBracket = new Op("("); static public Op Op_RightBracket = new Op(")"); static public Op Op_equal = new Op("=", 2, 10); static public Op Op_logic_or = new Op("||", 2, 15); static public Op Op_logic_and = new Op("&&", 2, 15); static public Op Op_greater = new Op(">", 2, 16); static public Op Op_greaterOrEqual = new Op(">=", 2, 16); static public Op Op_less = new Op("<", 2, 16); static public Op Op_lessOrEqual = new Op("<=", 2, 16); static public Op Op_logic_not = new Op("!", 1, 17); static public Op Op_isEqual = new Op("==", 2, 20); static public Op Op_notEqual = new Op("!=", 2, 20); static public Op Op_comma = new Op(",",0, 1); /// <summary> /// 中序表达式转逆波兰表达式 /// </summary> /// 中序表达式<param></param> /// <returns>逆波兰表达式</returns> static public List<item></item> GetRpnFromMn(List<item></item> input) { Stack<op></op> S1 = new Stack<op></op>(); List<item></item> S2 = new List<item></item>(); S1.Push(Op_lastOp); foreach (ITEM i in input) { if (i.GetType() == typeof(Data)) { S2.Add(i); } if (i.GetType() == typeof(Op)) { Op io = (Op)i; if (io.value == "(") { S1.Push(io); } else if (io.value == ")") { while (S1.Peek().value != "(") S2.Add(S1.Pop()); S1.Pop(); } else { if (io.priority > S1.Peek().priority) S1.Push(io); else { while (S1.Peek().priority >= io.priority && !(S1.Peek().cntOfData == 1 && S1.Peek().cntOfData == io.cntOfData)) { S2.Add(S1.Pop()); } S1.Push(io); } } } } if (S1.Count != 1) { while (S1.Count > 1) S2.Add(S1.Pop()); } //clear comma List<item></item> S3 = new List<item></item>(); foreach (ITEM i in S2) { if (i.value != ",") S3.Add(i); } return S3; } } public class RpnCalc { //运算主出口点 public RpnGenerator.Data Calc(List<rpngenerator.item></rpngenerator.item> l) { List<rpngenerator.data></rpngenerator.data> result = new List<rpngenerator.data></rpngenerator.data>(); while (l.Count > 0) { RpnGenerator.ITEM i = l.First(); l.RemoveAt(0); if (i.GetType() == typeof(RpnGenerator.Data)) { result.Add(GetData((RpnGenerator.Data)i)); } else { result.Add(CalcOp((RpnGenerator.Op)i, ref result)); } } return result.First(); } //原子表达式和函数运算,如果有额外的函数,需重载本函数 public virtual RpnGenerator.Data CalcOp(RpnGenerator.Op op, ref List<rpngenerator.data></rpngenerator.data> result) { RpnGenerator.Data d = new RpnGenerator.Data(""); switch (op.value) { //case RpnGenerator.Op_comma; case "=": //RpnGenerator.Op_equal.value: { RpnGenerator.Data rhs2 = result.Last(); result.RemoveAt(result.Count - 1); RpnGenerator.Data rhs1 = result.Last(); result.RemoveAt(result.Count - 1); SetData(rhs1, rhs2); d.value = "true"; } break; //case RpnGenerator.Op_lastOp: //case RpnGenerator.Op_leftBracket: case ">": //RpnGenerator.Op_greater: { RpnGenerator.Data rhs2 = result.Last(); result.RemoveAt(result.Count - 1); RpnGenerator.Data rhs1 = result.Last(); result.RemoveAt(result.Count - 1); int l1; int l2; l1 = int.Parse(rhs1.value); l2 = int.Parse(rhs2.value); d.value = (l1 > l2).ToString(); } break; case ">=": // RpnGenerator.Op_greaterOrEqual: { RpnGenerator.Data rhs2 = result.Last(); result.RemoveAt(result.Count - 1); RpnGenerator.Data rhs1 = result.Last(); result.RemoveAt(result.Count - 1); int l1; int l2; l1 = int.Parse(rhs1.value); l2 = int.Parse(rhs2.value); d.value = (l1 >= l2).ToString(); } break; case "==": //RpnGenerator.Op_isEqual: { RpnGenerator.Data rhs2 = result.Last(); result.RemoveAt(result.Count - 1); RpnGenerator.Data rhs1 = result.Last(); result.RemoveAt(result.Count - 1); d.value = (rhs1.value.ToLower().Trim() == rhs2.value.ToLower().Trim()).ToString(); } break; case "<": //RpnGenerator.Op_less: { RpnGenerator.Data rhs2 = result.Last(); result.RemoveAt(result.Count - 1); RpnGenerator.Data rhs1 = result.Last(); result.RemoveAt(result.Count - 1); int l1; int l2; l1 = int.Parse(rhs1.value); l2 = int.Parse(rhs2.value); d.value = (l1 < l2).ToString(); } break; case "<=": // RpnGenerator.Op_lessOrEqual: { RpnGenerator.Data rhs2 = result.Last(); result.RemoveAt(result.Count - 1); RpnGenerator.Data rhs1 = result.Last(); result.RemoveAt(result.Count - 1); int l1; int l2; l1 = int.Parse(rhs1.value); l2 = int.Parse(rhs2.value); d.value = (l1 <= l2).ToString(); } break; case "&&": //RpnGenerator.Op_logic_and: { RpnGenerator.Data rhs2 = result.Last(); result.RemoveAt(result.Count - 1); RpnGenerator.Data rhs1 = result.Last(); result.RemoveAt(result.Count - 1); bool l1; bool l2; l1 = bool.Parse(rhs1.value); l2 = bool.Parse(rhs2.value); d.value = (l1 && l2).ToString(); } break; case "!": // RpnGenerator.Op_logic_not: { RpnGenerator.Data rhs1 = result.Last(); result.RemoveAt(result.Count - 1); bool l1; l1 = bool.Parse(rhs1.value); d.value = (!l1).ToString(); } break; case "!=": // RpnGenerator.Op_notEqual: { RpnGenerator.Data rhs2 = result.Last(); result.RemoveAt(result.Count - 1); RpnGenerator.Data rhs1 = result.Last(); result.RemoveAt(result.Count - 1); d.value = (rhs1.value.ToLower().Trim() != rhs2.value.ToLower().Trim()).ToString(); } break; case "||": // RpnGenerator.Op_logic_or: { RpnGenerator.Data rhs2 = result.Last(); result.RemoveAt(result.Count - 1); RpnGenerator.Data rhs1 = result.Last(); result.RemoveAt(result.Count - 1); bool l1; bool l2; l1 = bool.Parse(rhs1.value); l2 = bool.Parse(rhs2.value); d.value = (l1 || l2).ToString(); } break; default: { throw new Exception("未处理的运算符或函数 - " + op.value); } } return d; } //取值 public virtual RpnGenerator.Data GetData(RpnGenerator.Data d) { return d; } //赋值 public virtual void SetData(RpnGenerator.Data lhs, RpnGenerator.Data rhs) { lhs = rhs; } }}
阅读全文
0 0
- 表达式计算
- 表达式计算
- 表达式计算
- 表达式计算
- 表达式计算
- 表达式计算
- 表达式计算
- 计算表达式
- 表达式计算
- 表达式计算
- 表达式计算
- 表达式计算
- 表达式计算 .
- 计算表达式
- 计算表达式
- 表达式计算
- 表达式计算
- 表达式计算
- drools
- 【金融财经】金融市场一周简报(2017-08-25)
- JAVA12_IO
- Python中的Scapy初探之三-ARP中毒
- 蒜头君的排序
- 表达式计算
- phantomjs fail-to-load-the-address问题的两个解决方法
- dbm和db的关系、区别
- 初学Redis(4)——简单实现Redis缓存中的排序功能
- 人工智能
- Leetcode#20: Valid Parentheses
- Android--BindService
- android popupwindow
- 设备兼容性