根據上面的分析得出,記號對象要求有一個存儲自身值的變量,有自己特定的計算方法,還要能知道其下級的值。由此可以得出 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