# 練習 36:簡單的計算器
> 原文:[Exercise 36: Simple Calculator](https://learncodethehardway.org/more-python-book/ex36.html)
> 譯者:[飛龍](https://github.com/wizardforcel)
> 協議:[CC BY-NC-SA 4.0](http://creativecommons.org/licenses/by-nc-sa/4.0/)
> 自豪地采用[谷歌翻譯](https://translate.google.cn/)
這個挑戰是創建一個簡單的代數計算器,使用你所學到的關于解析的一切。你將需要設計一種語言,用于使用變量進行基本數學運算,為該語言創建 ABNF,并為其編寫掃描器,解析器,分析器和解釋器。這實際上對于簡單的計算器語言可能是小題大做,因為不會有任何嵌套的結構,如函數,但是無論如何都要理解完整的過程。
## 挑戰練習
簡單的代數語言對于不同的人來說意思也不同,所以我希望你試試 Unix 命令`bc`。這是我運行`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
```
你需要創建變量,輸入數字(包括整數和浮點數),并擁有盡可能多的,你可以想到的運算符。你最有可能使用`bc`,甚至是 Python 的 shell,并且在你弄明白時候為它編寫 ABNF。請記住,你的 ABNF 幾乎是偽代碼,不必形式上正確,只需足夠接近來創建掃描器和解析器。
一旦“簡單制作”了 ABNF 形式的語法,你可以坐下來創建掃描器和解析器。我會寫一套簡單的腳本,來練習你認為語言應該做的事情,然后讓你的測試套件,在每個階段通過你的計算器運行它們。這樣做可以更容易地測試計算器。
完成解析器之后,你應該編寫一個分析器來鞏固嗎,并檢查輸入的語義。在這樣一種簡單的語言中,它可能不僅僅是你需要的東西,但這是一個練習,用小型玩具語言完成整個過程。請記住,分析器的重要任務是,跟蹤腳本中不同位置的變量定義,以便在執行過程中它們可由解釋器訪問。
在分析器創建可執行解析樹之后,你可以編寫一個運行它的解釋器。如練習 35 所述,你可以使用兩種方式來編寫解釋器。一個是你創建一個“機器”,知道如何運行語法產生式,作為一系列的輸入。這將把你的語法產生式類(`Expression`,`Assignment`等)視為機器代碼,并且簡單地執行它們所包含的內容。例如 Python 這樣的 OOP 語言的另一種風格是,讓每個產生式類知道如何運行自身。在這種風格中,這些類很“聰明”,并且接受他們的環境,只需要做他們需要做的事情,來使事情發生。然后,你只需“遍歷”語法產生式列表,并調用`run`,直到調用完畢。
你選擇哪一個,決定了你在哪里存儲你的小型解釋器的狀態。如果你制作`Interpreter`類,僅僅執行產生式數據對象,那么解釋器可以跟蹤所有的狀態,但語言更難擴展,因為你必須為每個產生式類改進`Interpreter`。如果你的產生式類知道如何執行自己的代碼,那么擴展語言很容易,但是你必須找到一種方法,在每個產生式之間傳遞計算機狀態。
處理它的時候,我建議你僅僅以一個非常小的表達式來起步,比如加法。讓整個系統首先能夠工作,從掃描器一直到運行簡單的加法。然后,如果你不喜歡這個設計,你可以把它丟掉,使用不同的設計重做。一旦你的設計能夠工作,你就可以使用更多功能來擴展語言。
## 研究性學習
+ 最好的研究性學習是創建函數來執行計算和返回結果。如果你可以這樣做,那么你的設計將可能適用于更大的語言。
+ 接下來要嘗試的是,使用`if`語句和`boolean`檢查來實現控制流。如果這太難了,那就對了,但請試試看。
## 深入學習
盡你所能來研究`bc`或 Python 語言。嘗試找到其他語法文件來閱讀和學習,特別是任何 IETF 協議的描述。IETF 的規范(像濕巾那樣)讓人興奮,但它們是個很好的練習。
- 笨辦法學 Python · 續 中文版
- 引言
- 第一部分:預備知識
- 練習 0:起步
- 練習 1:流程
- 練習 2:創造力
- 練習 3:質量
- 第二部分:簡單的黑魔法
- 練習 4:處理命令行參數
- 練習 5:cat
- 練習 6:find
- 練習 7:grep
- 練習 8:cut
- 練習 9:sed
- 練習 10:sort
- 練習 11:uniq
- 練習 12:復習
- 第三部分:數據結構
- 練習 13:單鏈表
- 練習 14:雙鏈表
- 練習 15:棧和隊列
- 練習 16:冒泡、快速和歸并排序
- 練習 17:字典
- 練習 18:性能測量
- 練習 19:改善性能
- 練習 20:二叉搜索樹
- 練習 21:二分搜索
- 練習 22:后綴數組
- 練習 23:三叉搜索樹
- 練習 24:URL 快速路由
- 第四部分:進階項目
- 練習 25:xargs
- 練習 26:hexdump
- 練習 27:tr
- 練習 28:sh
- 練習 29:diff和patch
- 第五部分:文本解析
- 練習 30:有限狀態機
- 練習 31:正則表達式
- 練習 32:掃描器
- 練習 33:解析器
- 練習 34:分析器
- 練習 35:解釋器
- 練習 36:簡單的計算器
- 練習 37:小型 BASIC
- 第六部分:SQL 和對象關系映射
- 練習 38:SQL 簡介
- 練習 39:SQL 創建
- 練習 40:SQL 讀取
- 練習 41:SQL 更新
- 練習 42:SQL 刪除
- 練習 43:SQL 管理
- 練習 44:使用 Python 的數據庫 API
- 練習 45:創建 ORM
- 第七部分:大作業
- 練習 46:blog
- 練習 47:bc
- 練習 48:ed
- 練習 49:sed
- 練習 50:vi
- 練習 51:lessweb
- 練習 52:moreweb