有關表示式求值的一些思考

2021-06-17 16:09:09 字數 2749 閱讀 5010

最近在實現乙個表示式的evaluator

具體來說,就是對表示式求值,算出最終的結果。

目前的這個版本的evaluator只針對常量表示式,對變數表示式則不去處理。因為對於變數表示式,是無

法在編譯期間求出其最終結果的,只有等到執行階段才具備算出結果的全部條件。

evaluator的實現機理並不太複雜,簡單來說,就是乙個遞迴下降的求值過程。如果把表示式的語法結構

表徵為一棵語法樹,那麼,evaluator的求值過程就類似於對這棵樹作後序遍歷

以常量表示式 1+2+3*4-5 為例,其相應的語法樹如下:

對這個常量表示式進行evaluate求值的過程就是乙個近似於後序遍歷的過程:

先求出左子樹的結果,再

求出右子樹的結果,然後再應用根結點上標識的操作符對左右子樹的結果作運算。對左右子樹的計算則遞

歸使用該計算過程。

具體到例子表示式中,就是先求出子樹(1+2)的結果,再求出子樹(3*4)的結果,再求子樹(1+2)+

(3*4)的結果,最後再求出語法樹((1+2)+(3*4))-5的結果。

看起來實現這個evaluator的思路還是比較直接的,但是再往深入想,就發現還會存在一些問題。

對於常量表示式而言,上面給出的evaluate求值過程是沒有什麼問題的。但是如果是乙個包含常量表達

式的變數表示式,對其中的常量子表示式,我們又應該怎樣處理呢?具體來說,就是像這樣的表達

式:a+2+1+b+(3*4),其中a,b皆為變數。在這個變數表示式中,存在了常量子表示式(如3*4),對

於這樣的常量子表示式,也是應該計算出其值的。但是考慮到這個變數表示式的語法樹會長成下面這個樣

子:

從這棵語法樹可以看出,可以看作常量子表示式的子語法樹只有(3*4)。所以在evaluate的過程中,我

們也需要將(3*4)的結果算出來,並用於替換掉(3*4)這個子表示式,算出來的結果是a+2+1+b+12

但是稍微一分析就會發現,這個結果並不是最優的結果,在a+2+1+b+(3*4)中,可以視為常量子表達

式的實際上還有2+1,並且再進一步,2+1的結果,還可以再與3*4的結果進行加法運算,如果通過人

肉分析,將這個變數表示式裡的所有常量元素全部進行求值處理的話,最優計算結果應該是a+b+15

其中15是((2+1)+(3*4))的計算結果。可以看出,表示式的原始語法樹表示形式限制了對變數表示式中

的常量分量的計算工作。想要解決這個問題,就需要對變數表示式的語法樹進行變形和轉換。如果能夠將

原始的語法樹變換成下面這個模樣:

再對其進行evaluate,算出來的結果就會是15+a+b,符合最優結果的要求了。

但是對語法樹進行變形和轉換,並不是一件非常容易的事情。如果表示式運算過程涉及到的運算子全部是

滿足結合率的運算,如:加法乘法的話,會很方便作變換,比如,對於變數表示式a+1+2,我們大

可通過合併常量分量的方式將其變換為a+(1+2),從而將常量分量集中在一起,便於對常量子表示式求

值。但如果變數表示式中還包括不滿足結合律的運算,如減法除法取模運算,情況就變得複雜得多

了。比如,對於a-1-2,想要將常量1和2結合起來,就需要變換成a-(1+2)的形式,這就在合併常量分

量的同時引入了一些變化了。再考慮除法,再考慮求模運算,再考慮移位呢?情況就變得更複雜一些了。

這個時候,就很希望自己的數學背景好一些,能夠對這種問題作乙個理論上的抽象分析。僅僅通過實證的

方式來分析這種情況,很容易陷入例項**的狀態,而且即使在給出了相當多的例項之後,還是擔心自己

會遺漏了某些點。而如果從數學角度,在抽象層面作乙個定性的分析,就很有幫助了。

p.s.gcc試了一下,對這樣的表示式:a-1+a-(2-1)*2,開啟-o1選項以後,gcc就會將其優化為

a+a-3了,所以我想這種常量表示式的優化技術在現代編譯器裡應該是比較經典的技術了,只不過因為

現在自己還欠缺這方面的積累,所以一時沒有太好的辦法,也許自己會在某個時候好好研究一下gcc或是

lcc這樣的現代編譯器的實現來作為自己的參考吧。

有關perl正規表示式的一些雜項

也能匹配 n 見perl語言入門,page 132,注釋6 1 能匹配 n 麼?能!因為 不僅能匹配行尾,也能匹配 n 2 能匹配 b n 麼?能!能b匹配.n匹配 3 能匹配 nb 麼?不能!為什麼?因為預設情況下,不能匹配 n,把模式改一下變成 s就可以了,s表示.能匹配任意字元,包括 n 多行...

一些正規表示式

要嚴格的驗證手機號碼,必須先要清楚現在已經開放了哪些數字開頭的號碼段,目前國內號碼段分配如下 移動 134 135 136 137 138 139 150 151 157 td 158 159 187 188 聯通 130 131 132 152 155 156 185 186 電信 133 153...

一些正規表示式

判斷是否是正整數if isnan paramvalue paramvalue 0 else 金額的格式判斷輸入金額的要求 整數字最多十位,小數為最多為兩位,可以無小數字 0 9 1 9 0 9 0 9 function checkmoney str 0 9 if re.test str else 手...