一、問題的提出
假如我們有如下所示的與/或表達式:
a*[b*[c+d]*e+f]+g
化簡後要得到如下的表達式:
a*b*c*e+a*b*d*e+a*f+g
表達式中允許的字母和算符
{A-Z, a-z, [,],*,+}
其中“[,]”表示括號,允許嵌套;“*”表示邏輯運算符“與”;“+”表示邏輯運算符“或”;並且“*”的優先級高於“+”。
二、解決辦法
在編譯原理中,有一種自上而下分析方法LL(1),其核心算法就是“遞歸下降法”,其具體理論有興趣的朋友可以參考一些編譯原理書籍。首先讓我們來看一個編譯原理課本上用“遞歸下降法”進行“表達式的求值”的分析得到的產生式:
exp->exp addop term|term
addop->+|-
term->term mulop factor|factor
mulop->*
factor->(exp)|number
其中“exp”代表待求值的表達式;“addop”代表“+”和“-”運算符;“term”代表用“*”連接起來的表達式;“mulop”代表“*”;“factor”代表乘積因子,它可以是一個數,也可以是一個表達式。
按照這種思路,我得出了如下的對應於本文開頭所提出問題的產生式:
exp->term { OR term }|term
OR->+
term->term AND factor|factor
AND->*
factor->[exp]|letter
letter->[A-Z]|[a-z]
去除左遞歸後如下所示:
exp->term { OR term }
OR->+
term->factor { AND factor }
factor->letter|[exp]
AND->*
letter->[A-Z]|[a-z]
這樣,我們就很容易將其轉化為代碼。比如,將“exp->term { OR term }”這個表達式轉化的偽代碼如下:
CString exp()
{
CString temp = _T("");
try
{
temp = Term();
while( 當前還沒有到輸入串的末尾 && 下一個將要掃描的字符為OR )
{
temp += "+";
Match(OR);//字符匹配,用戶判斷將要掃描的字符是否為所期望的字符,並且推動掃描串的前進
temp += Term();
}
}
catch(CError& error)
{
throw error;
}
return temp;
}
其它的產生式對應的代碼類似,具體細節就不敘述了,請大家參考參考源程序。
三、運行效果圖
四、結束語
這是我第一次在VCKBASE上發表的文章,其中肯定存在許多不足之處,希望大家指出來批評指正
^-^。同時,我也感覺到深為一名學習計算機的學生,豐富的編程實際經驗固然重要,但如果具有豐富的理論基礎作為堅強後盾的話,那麼我們在編寫程序時就會游刃有余,才會感覺到寫程序是一種真正的享受^-^。
本文配套源碼