練習(xí) 36:簡單的計算器
譯者:飛龍
協(xié)議:CC BY-NC-SA 4.0
自豪地采用谷歌翻譯
這個挑戰(zhàn)是創(chuàng)建一個簡單的代數(shù)計算器,使用你所學(xué)到的關(guān)于解析的一切。你將需要設(shè)計一種語言,用于使用變量進(jìn)行基本數(shù)學(xué)運(yùn)算,為該語言創(chuàng)建 ABNF,并為其編寫掃描器,解析器,分析器和解釋器。這實(shí)際上對于簡單的計算器語言可能是小題大做,因?yàn)椴粫腥魏吻短椎慕Y(jié)構(gòu),如函數(shù),但是無論如何都要理解完整的過程。
挑戰(zhàn)練習(xí)
簡單的代數(shù)語言對于不同的人來說意思也不同,所以我希望你試試 Unix 命令bc。這是我運(yùn)行bc命令的一個例子:
$ bc
bc 1.06
Copyright 1991-1994, 1997, 1998, 2000 Free Software Foundation, Inc.
This is free software with ABSOLUTELY NO WARRANTY.
For details type `warranty'.
x = 10
y = 11
j = x * y
j
110
你需要創(chuàng)建變量,輸入數(shù)字(包括整數(shù)和浮點(diǎn)數(shù)),并擁有盡可能多的,你可以想到的運(yùn)算符。你最有可能使用bc,甚至是 Python 的 shell,并且在你弄明白時候?yàn)樗帉?ABNF。請記住,你的 ABNF 幾乎是偽代碼,不必形式上正確,只需足夠接近來創(chuàng)建掃描器和解析器。
一旦“簡單制作”了 ABNF 形式的語法,你可以坐下來創(chuàng)建掃描器和解析器。我會寫一套簡單的腳本,來練習(xí)你認(rèn)為語言應(yīng)該做的事情,然后讓你的測試套件,在每個階段通過你的計算器運(yùn)行它們。這樣做可以更容易地測試計算器。
完成解析器之后,你應(yīng)該編寫一個分析器來鞏固嗎,并檢查輸入的語義。在這樣一種簡單的語言中,它可能不僅僅是你需要的東西,但這是一個練習(xí),用小型玩具語言完成整個過程。請記住,分析器的重要任務(wù)是,跟蹤腳本中不同位置的變量定義,以便在執(zhí)行過程中它們可由解釋器訪問。
在分析器創(chuàng)建可執(zhí)行解析樹之后,你可以編寫一個運(yùn)行它的解釋器。如練習(xí) 35 所述,你可以使用兩種方式來編寫解釋器。一個是你創(chuàng)建一個“機(jī)器”,知道如何運(yùn)行語法產(chǎn)生式,作為一系列的輸入。這將把你的語法產(chǎn)生式類(Expression,Assignment等)視為機(jī)器代碼,并且簡單地執(zhí)行它們所包含的內(nèi)容。例如 Python 這樣的 OOP 語言的另一種風(fēng)格是,讓每個產(chǎn)生式類知道如何運(yùn)行自身。在這種風(fēng)格中,這些類很“聰明”,并且接受他們的環(huán)境,只需要做他們需要做的事情,來使事情發(fā)生。然后,你只需“遍歷”語法產(chǎn)生式列表,并調(diào)用run,直到調(diào)用完畢。
你選擇哪一個,決定了你在哪里存儲你的小型解釋器的狀態(tài)。如果你制作Interpreter類,僅僅執(zhí)行產(chǎn)生式數(shù)據(jù)對象,那么解釋器可以跟蹤所有的狀態(tài),但語言更難擴(kuò)展,因?yàn)槟惚仨殲槊總€產(chǎn)生式類改進(jìn)Interpreter。如果你的產(chǎn)生式類知道如何執(zhí)行自己的代碼,那么擴(kuò)展語言很容易,但是你必須找到一種方法,在每個產(chǎn)生式之間傳遞計算機(jī)狀態(tài)。
處理它的時候,我建議你僅僅以一個非常小的表達(dá)式來起步,比如加法。讓整個系統(tǒng)首先能夠工作,從掃描器一直到運(yùn)行簡單的加法。然后,如果你不喜歡這個設(shè)計,你可以把它丟掉,使用不同的設(shè)計重做。一旦你的設(shè)計能夠工作,你就可以使用更多功能來擴(kuò)展語言。
研究性學(xué)習(xí)
- 最好的研究性學(xué)習(xí)是創(chuàng)建函數(shù)來執(zhí)行計算和返回結(jié)果。如果你可以這樣做,那么你的設(shè)計將可能適用于更大的語言。
- 接下來要嘗試的是,使用
if語句和boolean檢查來實(shí)現(xiàn)控制流。如果這太難了,那就對了,但請試試看。
深入學(xué)習(xí)
盡你所能來研究bc或 Python 語言。嘗試找到其他語法文件來閱讀和學(xué)習(xí),特別是任何 IETF 協(xié)議的描述。IETF 的規(guī)范(像濕巾那樣)讓人興奮,但它們是個很好的練習(xí)。