基於文本替換的解譯器:加入整數類型

來源:互聯網
上載者:User

為了有條不紊地實現一個解譯器,我將按以下三個步驟走:

1.明確文法

2.針對文法描述求值過程

3.根據求值過程編寫代碼實現

文法

\(\lambda\)演算不適合作為一門實際使用的程式語言。 \(\lambda\)演算只有變數和函數兩種類型,而其他常用類型如整數、布爾、字元等都沒有。 雖然可以通過編碼的方式表示這些常用類型,但這樣也很麻煩。 通常直接擴充\(\lambda\)演算,加入一些常用類型以及針對這些類型的基本運算。 這種擴充後的語言簡稱為ISWIM,全稱未知……

為簡單起見,我只加入整數類型,以及加法和減法。 擴充後的文法如下: \begin{eqnarray*} M, N, L &=& X \\ &|& b \\ &|& \lambda X.M \\ &|& (+ \; M \; N) \\ &|& (- \; M \; N) \\ &|& (M \; N) \end{eqnarray*} 新加入的第二行\(b\)表示一個整數, 第四行是一個加法運算的運算式, 第五行是一個減法運算的運算式。

求值過程

為了描述一個計算這門語言的解譯器的求值過程,首先要明確求值停止條件。 我們規定當歸約到\(X\),\(b\),\(\lambda X.M\)這三種運算式之一時,認為解譯器已經求出了最終結果。 這三種運算式稱為值,用字母\(V\)表示。 \begin{eqnarray*} V &=& X \\ &|& b \\ &|& \lambda X.M \end{eqnarray*}

用記號\(eval(M)\)表示運算式\(M\)的求值結果。 對於值,求值只需返回它們自身。 \begin{eqnarray*} eval(X) &=& X \\ eval(b) &=& b \\ eval(\lambda X.M) &=& \lambda X.M \end{eqnarray*} 加減法和函數調用這三行是遞迴定義,所以求值過程也是遞迴的。 \begin{eqnarray*} eval((+ \; M \; N)) &=& eval((+ \; V_1 \; V_2)) \\ eval((- \; M \; N)) &=& eval((- \; V_1 \; V_2)) \\ eval((M \; N)) &=& eval((V_1 \; V_2)) \end{eqnarray*} 其中\(V_1=eval(M)\),\(V_2=eval(N)\)。

為了讓解譯器盡量簡單,假設輸入的程式是正確的。 也就是說,對於加減法運算的\(V_1\)和\(V_2\)都是整數,記為\(b_1\)和\(b_2\); 函數調用裡的\(V_1\)是一個函數\(\lambda X.L\)。

加減法如字面本意,就是作加減法。 函數調用過程是一個\(\beta\)歸約過程。 \begin{eqnarray*} eval((+ \; b_1 \; b_2)) &=& b_1 + b_2 \\ eval((- \; b_1 \; b_2)) &=& b_1 - b_2 \\ eval((\lambda X.L \; V_2)) &=& eval(L[X \leftarrow V_2]) \end{eqnarray*}

由於加入了新的文法,替換過程也要添加相應的過程。 這裡列上整個替換過程: \begin{eqnarray*} X_1[X_1 \leftarrow N] &=& N \\ X_2[X_1 \leftarrow N] &=& X_2 \\ &&其中X_1 \neq X_2 \\ b[X \leftarrow N] &=& b \\ (\lambda X_1.M)[X_1 \leftarrow N] &=& (\lambda X_1.M) \\ (\lambda X_1.M)[X_2 \leftarrow N] &=& (\lambda X_3.M[X_1 \leftarrow X_3][X_2 \leftarrow N]) \\ &&其中X_1 \neq X_2, X_3 \notin FV(N), X_3 \notin FV(M)\backslash\{X_1\} \\ (+ \; M_1 \; M_2)[X \leftarrow N] &=& (+ \; M_1[X \leftarrow N] \; M_2[X \leftarrow N]) \\ (- \; M_1 \; M_2)[X \leftarrow N] &=& (- \; M_1[X \leftarrow N] \; M_2[X \leftarrow N]) \\ (M_1 \; M_2)[X \leftarrow N] &=& (M_1[X \leftarrow N] \; M_2[X \leftarrow N]) \end{eqnarray*}

最後總結求值過程如下: \begin{eqnarray*} eval(X) &=& X \\ eval(b) &=& b \\ eval(\lambda X.M) &=& \lambda X.M \\ eval((+ \; M \; N)) &=& eval(M) + eval(N) \\ eval((- \; M \; N)) &=& eval(M) - eval(N) \\ eval((M \; N)) &=& eval(L[X \leftarrow eval(N)]) \\ && 其中 eval(M) = \lambda X.L \end{eqnarray*}

實現

這裡使用Racket語言來編寫解譯器。 解譯器輸入不使用字串,而是用Racket的符號系統。 使用符號系統是為了簡化文法分析的工作。 利用Racket的模式比對可以方便地實現文法分析。 另外,電腦輸入\(\lambda\)還是很麻煩的,所以在具體實現的語言中用(lambda X M)代替\(\lambda X.M\)。

解譯器是一個實現了\(eval\)函數的程式。 代碼是求值過程的公式逐句轉換,就不一一解釋了。 value-of是求值過程:

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.