2014-10-01 24 views
1

考慮下面的表達式解析算術/布爾表達式,但跳過捕獲

x = a + 3 + b * 5 

我還想寫在下面的數據結構,其中我只關心捕獲到RHS使用的變量,並保持該字符串完好無損。在解析更具體的結構,因爲我在做從語言到語言的轉換,而不是處理我一直在使用this tutorial作爲我的出發點評價

Variable "x" (Expr ["a","b"] "a + 3 + b * 5") 

不感興趣,但我不知道如何寫沒有buildExpressionParser的表達式分析器。這似乎不是我應該這樣做的方式。

回答

1

我不知道爲什麼要避免使用buildExpressionParser,因爲它隱藏了很多使用中綴運算符分析表達式的複雜性。這是正確方式做事情....

對不起,但現在,我得到了嘮叨的方式,我可以回答你的問題。

首先,這裏是一些背景 -

的主要原因寫有中綴運算符的表達式解析器是很難,因爲運算符優先級。你要確保這個

x+y*z 

分析,因爲這

+ 
/\ 
x * 
    /\ 
    y z 

,而不是這個

* 
/\ 
    + z 
/\ 
x y 

選擇正確的分析樹不是解決一個非常困難的問題...但如果你不注意,你可以編寫一些非常糟糕的代碼。爲什麼?性能....

忽略優先級的可能parsetrees的數量隨着輸入的大小呈指數增長。例如,如果您編寫代碼嘗試所有可能性,然後丟棄除正確優先級以外的所有可能性,那麼當解析器解決現實世界中的任何問題時,您將會有一個令人討厭的驚喜(請記住,指數複雜性通常不僅很慢,它基本上不是一個解決方案....你可能會發現你正在等待半個小時進行簡單的解析,沒有人會使用該解析器)。

我不會在這裏重複「適當」解決方案的細節(谷歌搜索會給出細節),除非要注意適當的解決方案在輸入大小的O(n)下運行,而且buildExpressionParser隱藏了爲你編寫這樣一個解析器的所有複雜性。


所以,回到你原來的問題....

你需要使用buildExpressionParser得到變量了RHS的,或者是有沒有更好的辦法?

你並不需要 ....

因爲所有你關心的是獲得在右側使用的變量,你不關心運算符優先級。您可以將所有內容都關聯起來,然後編寫一個簡單的O(n)解析器。分析樹會是錯誤的,但誰在乎?你仍然會得到相同的變量。你甚至都不需要一個上下文無關文法這一點,這個正則表達式基本上沒有它

<variable>(<operator><variable>)* 

(其中<variable><operator>在明顯的方式定義)。

但是....

我不會推薦這一點,因爲,就這麼簡單,因爲它是,它仍然會比使用buildExpressionParser更多的工作。延伸會更棘手(如添加括號)。但是最重​​要的是,稍後您可能會意外地在某處需要完整的解析器的地方使用它,並且會困惑一會兒,爲什麼操作符優先級完全搞砸了。

另一個解決方案是,你可以重寫你的語法來消除歧義(再次,谷歌會告訴你如何)....這將是一個很好的學習練習,但你基本上會重複buildExpressionParser在內部做什麼。