首页 / 软件开发 / C# / 仿查询分析器的C#计算器——2.记号对象
仿查询分析器的C#计算器——2.记号对象2011-07-16 博客园 conexpress上一篇中提到了用树形结构来分析表达式并计算求值的思路。但对程序来说,输入的表达式只是一个字符串而已。要将表达式表示成树型结 构,首先必须可以将表达式分解成一个个节点,然后才可以由节点组成树。这里将树上的每一个节点称之为记号对象TokenRecord。根据上面的分析得出,记号对象要求有一个存储自身值的变量,有自己特定的计算方法,还要能知道其下级的值。由此可以得出 TokenRecord的基本信息(略去非关键信息):属性Index:在表达式中的列号,int类型,出错时用于指示错误所在,从1开始。Priority:优先级,int类型,在分析表达式的时候需要。TokenValue:记号值,object类型ChildList:下级列表,List对象,用来存储下级元素,实现树结构。方法Execute:执行该元素的操作,abstract方法。SetChildCount:设置下级数量,虚方法,用于检查下级数量合法性,在构造函数中调用。对应有一个m_ChildCount字段,用于存储下级数 量。因为检查下级属于元素内部的任务,所以将m_ChildCount设置为protected,也没有对应的ChildCount属性。SetPriority:设置优先级,虚方法,在构造函数中调用。CheckChildCount:检查下级数量,在Execute中调用,保证表达式合法。其中TokenValue属性使用object类型是因为这里支持字符串、数值和逻辑值的运算。在最开始设计的时候,曾经采用过两个字段string和 double类型来存储字符串和数值,逻辑值也用数值表示,后来改成object更简单了。TokenRecord类的代码如下:/// <summary> /// 记号对象 /// </summary> /// <remarks>Author:Alex Leo;</remarks> public abstract class TokenRecord { #region 属性和字段 //下级个数 protected int m_ChildCount; private int m_Index; /// <summary> /// 列序号 /// </summary> public int Index { get { return m_Index; } } /// <summary> /// 优先级,必须赋值 /// </summary> protected int m_Priority; /// <summary> /// 优先级 /// </summary> /// <returns></returns> public int Priority { get { return m_Priority; } } private int m_Length; /// <summary> /// 操作符长度 /// </summary> public int Length { get { return m_Length; } } private Type m_TokenValueType; /// <summary> /// 记号值类型 /// </summary> public Type TokenValueType { get { return m_TokenValueType; } set { m_TokenValueType = value; } } private object m_TokenValue; /// <summary> /// 记号值 /// </summary> public object TokenValue { get { return m_TokenValue; } set { m_TokenValue = value; } } private List<TokenRecord> m_ChildList = new List<TokenRecord>(); /// <summary> /// 下级列表 /// </summary> public List<TokenRecord> ChildList { get { return m_ChildList; } } #endregion /// <summary> /// 构造函数 /// </summary> /// <param name="Index">序号</param> /// <param name="Length">自身长度</param> public TokenRecord(int Index, int Length) { this.m_Index = Index; this.m_Length = Length; this.SetPriority(); this.SetChildCount(); } #region 方法 /// <summary> /// 重写ToString方法 /// </summary> /// <returns></returns> public override string ToString() { //可以根据需要修改以显示不同的信息 return this.GetType().Name + "_" + GetValueString() + "_" + TokenValueType.ToString(); } /// <summary> /// 获取值的字符串表示 /// </summary> /// <returns></returns> public string GetValueString() { return this.TokenValue.ToString(); } /// <summary> /// 检查下级数量,必要时可以重写,因为有些Token的下级数量可以是一个区间 /// </summary> /// <param name="ErrorInformation">下级数量不符时显示的错误信息</param> internal void CheckChildCount(string ErrorInformation) { if (this.m_ChildList.Count != this.m_ChildCount) throw new SyntaxException(this.m_Index, this.m_Length, ErrorInformation); } #region 必须重写的方法 /// <summary> /// 执行代码 /// </summary> public abstract void Execute(); /// <summary> /// 设置下级数量 /// </summary> protected abstract void SetChildCount(); /// <summary> /// 设置优先级 /// </summary> protected abstract void SetPriority(); #endregion #endregion #region 转换记号值类型 /// <summary> /// 将记号值转换为字符串类型 /// </summary> internal string ChangeTokenToString() { string strValue; strValue = (string)(this.TokenValue = this.TokenValue.ToString()); this.TokenValueType = typeof(string); return strValue; } /// <summary> /// 将记号值转换为数字类型 /// </summary> /// <param name="ErrorInformation">无法转换成数字时显示的错误信息</param> internal double ChangeTokenToDouble(string ErrorInformation) { double dblValue; if (this.TokenValueType != typeof(double)) { if (double.TryParse(this.TokenValue.ToString(), out dblValue)) this.TokenValueType = typeof(double); else throw new SyntaxException(this.m_Index, this.m_Length, ErrorInformation); } else { dblValue = (double)this.TokenValue; } return dblValue; } /// <summary> /// 将记号值转换为逻辑值 /// </summary> internal bool ChangeTokenToBoolean() { bool blnValue = false; if (this.TokenValueType == typeof(string)) { switch (this.TokenValue.ToString().Trim().ToLower()) { case "true": blnValue = (bool)(this.TokenValue = true); break; case "false": case "": default: blnValue = (bool)(this.TokenValue = false); break; } this.TokenValueType = typeof(bool); } else if (this.TokenValueType == typeof(double)) { blnValue = (bool)((Convert.ToInt32(this.TokenValue) != 0) ? (this.TokenValue = true) : (this.TokenValue = false)); //检查上一行代码是否错误 this.TokenValueType = typeof(bool); } else if (this.TokenValueType == typeof(bool)) { blnValue = (bool)this.TokenValue; } else { } return blnValue; } #endregion }//class TokenRecord
收藏该网址