2011-05-30 43 views
6

我正在構建一個表達式分析器,我想從中生成數據庫查詢代碼,但已經相當遠了,但我堅持精確地解析BinaryExpressions。將它們分解爲左和右是相當容易的,但我需要檢測括號並相應地生成我的代碼,我看不出如何執行此操作。在BinaryExpression中檢測括號

爲例[請忽略硬傷邏輯:)]:

a => a.Line2 != "1" && (a.Line2 == "a" || a.Line2 != "b") && !a.Line1.EndsWith("a") 

我需要在中間檢測「設置」,並維護他們的分組,但我看不到在表達什麼區別正常BinaryExpression解析過程中(我討厭檢查字符串表示括號)

任何幫助,將不勝感激。

(我也許應該提到,我使用C#)

- 編輯 - 我沒有提到,我使用標準的.NET表達式類建立表達式(System.Linq的。表達式命名空間)

- 編輯2--好吧我不解析文本到代碼中,我解析代碼到文本中。所以,我的解析器類有這樣的方法:

void FilterWith<T>(Expression<Func<T, bool>> filterExpression); 

,它允許你寫這樣的代碼:

FilterWith<Customer>(c => c.Name =="asd" && c.Surname == "qwe"); 

這是很容易使用標準的.NET類分析,我的挑戰是解析這個表達式:

FilterWith<Customer>(c => c.Name == "asd" && (c.Surname == "qwe" && c.Status == 1) && !c.Disabled) 

我的挑戰是保持括號之間的表達式作爲一個單一的集合。 .Net類正確地將括號中的部分與其他部分分開,但由於括號的原因,沒有指出它是一個集合。

+2

我只會觀察到,這比想象中更難(已經做了幾次),並且是許多「玩具」解析示例無法解決的問題。 – 2011-05-30 13:10:13

+1

遞歸體裁解析器很容易上手,任何有關編譯器構建的大學級別介紹性文本都會討論它。括號由生產expr =「(」+ expr +「)」處理。儘管如此,幾乎不需要重新創建這種代碼。即使.NET有一個:DataTable.Compute()。 – 2011-05-30 15:34:15

+0

小心分享你在這個問題上所做的一切嗎?我同意,這個例子是這個主題的基本方法... – 2011-05-30 15:37:14

回答

6

我自己並沒有使用表達式,但是如果它和任何其他AST一樣工作,那麼這個問題比你想象的更容易解決。正如另一位評論者指出的,只需在你的二進制表達式的全部的圓括號內,然後你就不必擔心操作問題的順序。

或者,您可以檢查您正在生成的表達式是否比包含表達式的優先級低,如果是,則將括號括起來。所以如果你有這樣一棵樹[* 4 [+ 5 6]](其中樹節點遞歸地表示爲[node left-subtree right-subtree]),當你寫出[+ 4 5]樹時,你會知道它包含在*操作中,它的優先級高於+操作,因此需要它的任何直接子樹都放在括號內。僞代碼可能是這樣的:

function parseBinary(node) { 
    if(node.left.operator.precedence < node.operator.precedence) 
     write "(" + parseBinary(node.left) + ")" 
    else 
     write parseBinary(node.left) 
    write node.operator 
    // and now do the same thing for node.right as you did for node.left above  
} 

你需要具有優先權的表爲各運營商,以及一種方式來獲得在運營商自己,找出它是什麼,那裏是什麼它的優先級是。不過,我想你可以指出這一點。

+0

據我所知,沒有「優先」,那麼遞歸分析AndAlso和OrElse並將括號放在每個地方都比較簡單。 – Jerther 2015-12-05 03:26:41

0

構建表達式分析器時,首先需要一個解析器,爲此您需要一個標記器。

標記器是一段代碼,用於讀取表達式,爲確定的語法生成標記(可以是有效的或無效的)。

因此,使用標記器的解析器按照建立的順序(從左到右,從右到左,從上到下,無論您選擇什麼)讀取表達式,並創建映射表達式的樹。

然後分析器將樹解釋爲一個表達式,給出它的確定含義。

+0

嗯,不知道我明白你的意思。我正在使用標準的.Net表達式類(System.Linq.Expressions命名空間),我現在看到的是BinaryExpression ... – 2011-05-30 15:36:02

+2

@Adriaan:等等,你是從字符串到表達式樹,還是表達式樹到字符串?如果生成一個字符串,你可以在每個子表達式周圍發出括號。 – 2011-05-30 15:44:37

+0

我認爲這個例子是表達式字符串... – configurator 2011-05-30 17:20:54