首先介紹關鍵字工廠 TokenKeywordFactory。當 TokenFactory 分析到英文字母時,將任務轉交給 TokenKeywordFactory。該類別從第一個英文字母開始向後分析,若後續為英文字母或數字則繼續,否則結束。關鍵字允許包含數字,但第一字元必須為英文字母。分析結束後截取字串,交給 ProduceToken 產生 TokenRecord 實例。
在 ProduceToken 中,先判斷傳入字串是否存在關鍵字字典,不存在則報錯,存在則用反射產生對應類別實例。部分關鍵字為常數,需特殊處理設定記號物件值與類型。
完成後調整分析指標位置,回到 TokenFactory 繼續後續分析。代碼如下:
internal class TokenKeywordFactory : TokenFactory
{
private static SortedDictionary<string, string> m_DictionaryKeyWord = new SortedDictionary<string, string>();
internal static SortedDictionary<string, string> GetKeywordDictionary()
{
if (m_DictionaryKeyWord.Count == 0) m_DictionaryKeyWord = TokenFactory.GetOperateTokenDictionary(OperateTokenTypeEnum.TokenKeyword);
return m_DictionaryKeyWord;
}
public static new void LexicalAnalysis(List<TokenRecord> TokenList, string Code, ref int Index)
{
int intIndexCurrent = Index; bool blnContinue = true; char chrTemp; string strTempWord = "";
while (blnContinue && intIndexCurrent < Code.Length)
{
chrTemp = Code[intIndexCurrent];
if (char.IsLetter(chrTemp) || char.IsDigit(chrTemp)) intIndexCurrent += 1;
else blnContinue = false;
}
strTempWord = Code.Substring(Index, intIndexCurrent - Index);
TokenRecord Token = ProduceToken(strTempWord, Index);
TokenList.Add(Token);
Index = intIndexCurrent - 1;
}
protected static new TokenRecord ProduceToken(string TokenWord, int Index)
{
TokenRecord Token;
if (GetKeywordDictionary().ContainsKey(TokenWord.ToLower()))
{
string strFullClassName = "ConExpress.Calculator." + GetKeywordDictionary()[TokenWord.ToLower()];
Type TokenType = Type.GetType(strFullClassName);
Token = (TokenRecord)Activator.CreateInstance(TokenType, new object[] { Index, TokenWord.Length });
// 常數特殊處理
switch (TokenWord.ToLower())
{
case "pi": Token.TokenValueType = typeof(double); Token.TokenValue = Math.PI; break;
case "e": Token.TokenValueType = typeof(double); Token.TokenValue = Math.E; break;
case "true": Token.TokenValueType = typeof(bool); Token.TokenValue = true; break;
case "false": Token.TokenValueType = typeof(bool); Token.TokenValue = false; break;
default: break;
}
}
else throw new SyntaxException(Index, TokenWord.Length, "未知運算式:" + TokenWord);
return Token;
}
}