首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

仿 SQL 查詢分析器的 C# 計算器(三):TokenRecord 基礎類別設計與核心屬性方法

     編輯:關於C語言

上一篇提到用樹狀結構分析運算式並計算求值。但對程式來說,輸入運算式只是字串。要表示成樹狀結構,必須先將運算式分解成節點,再由節點組成樹。這裡將樹上每個節點稱為記號物件 TokenRecord。

根據分析,記號物件需求:擁有儲存自身值的變數、特定計算方法、知道下層節點值。由此得出 TokenRecord 基本資訊(略去非關鍵資訊):

屬性

  • Index:運算式中的列號(int),出錯時指示錯誤位置,從 1 開始。
  • Priority:優先級(int),分析運算式時需要。
  • TokenValue:記號值(object)。
  • ChildList:下層清單(List<TokenRecord>),儲存下層元素,實現樹結構。

方法

  • Execute:執行該元素操作(abstract)。
  • SetChildCount:設定下層數量(virtual),建構子中調用,配合 m_ChildCount 欄位檢查下層數量合法性。
  • SetPriority:設定優先級(virtual),建構子中調用。
  • CheckChildCount:檢查下層數量,在 Execute 中調用,保證運算式合法。

TokenValue 用 object 是因為支援字串、數值、邏輯值運算。早期曾用 string 和 double 兩欄位,邏輯值用數值表示,後改用 object 更簡單。

TokenRecord 類別完整代碼

public abstract class TokenRecord
{
    #region 屬性和欄位
    protected int m_ChildCount;
    private int m_Index;
    public int Index { get { return m_Index; } }
    protected int m_Priority;
    public int Priority { get { return m_Priority; } }
    private int m_Length;
    public int Length { get { return m_Length; } }
    private Type m_TokenValueType;
    public Type TokenValueType { get { return m_TokenValueType; } set { m_TokenValueType = value; } }
    private object m_TokenValue;
    public object TokenValue { get { return m_TokenValue; } set { m_TokenValue = value; } }
    private List<TokenRecord> m_ChildList = new List<TokenRecord>();
    public List<TokenRecord> ChildList { get { return m_ChildList; } }
    #endregion

    public TokenRecord(int Index, int Length)
    { this.m_Index = Index; this.m_Length = Length; this.SetPriority(); this.SetChildCount(); }

    #region 方法
    public override string ToString() { return this.GetType().Name + "_" + GetValueString() + "_" + TokenValueType.ToString(); }
    public string GetValueString() { return this.TokenValue.ToString(); }
    internal void CheckChildCount(string ErrorInformation)
    { if (this.m_ChildList.Count != this.m_ChildCount) throw new SyntaxException(this.m_Index, this.m_Length, ErrorInformation); }

    #region 必須覆寫的方法
    public abstract void Execute();
    protected abstract void SetChildCount();
    protected abstract void SetPriority();
    #endregion
    #endregion

    #region 轉換記號值類型
    internal string ChangeTokenToString() { string strValue = (string)(this.TokenValue = this.TokenValue.ToString()); this.TokenValueType = typeof(string); return strValue; }
    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;
    }
    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;
        return blnValue;
    }
    #endregion
}
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved