2012-02-01 78 views
3

如何強制GLR方法解決shift/reduce衝突?
假設我想讓解析器解決右移運算符與模板參數的兩個閉角尖括號之間的衝突。我讓詞法分析器將連續2個「>」符號作爲單獨的標記傳遞,而不將它們合併爲一個單獨的「>>」標記。然後我把這些規則的語法:Bison,C++ GLR解析:如何強制轉移減少衝突?

operator_name: 
    "operator" ">" 
    | "operator" ">" ">" 
; 

我希望這是一個轉變\減少衝突。如果我有左結合的「>」令牌聲明,這不會是衝突。因此,我必須刪除令牌優先\關聯聲明,但這會導致許多其他衝突,我不想通過爲每個衝突規則指定上下文優先級來手動解決。那麼,是否有辦法在聲明令牌時強制轉換\減少衝突?

+0

「+1」考慮「>」作爲單獨的標記,而不是移位運算符或模板結束標記標記。對於「 - 」,負號或減法運算符會發生同樣的情況。 – umlcat 2012-02-01 16:56:29

+0

是的,我記得在C#和Java中使用這種技術,但這些解析器是基於ANTLR的,並且它更簡單一些,儘管並非沒有一些黑客。 – slavasav 2012-02-02 10:15:36

回答

2

我認爲,對OPERATOR_NAME規則使用context-dependent precedence會工作。

由更新的標準中規定的C++語法實際修改語法接受>>令牌關閉兩個打開的模板聲明。我建議遵循它來獲得標準的行爲。例如,你必須要小心,「X>> Y」不會被解析爲「x >> y」的,你還必須確保「富<酒吧< 2 >> 1 >>」是無效的,而「富< bar <(2 >> 1)>>「是有效的。

+0

事實證明,野牛認爲衝突解決了,當你指定上下文相關的優先順序。也就是說,如果我明確指出我希望第一條規則的優先級與第二條規則的優先級相同以便進行shift \ reduce衝突,那麼bison會選擇移位而不是讓衝突由glr來解決運行。 – slavasav 2012-02-02 10:14:30

0

我在Yacc工作(類似於Bison),有類似的場景。

標準語法有時被稱爲「由語法指導的解析」。

有時候,這種情況被稱爲「解析由語義引導」。

例子:

... 
// shift operator example 
if ((x >> 2) == 0) 
... 
// consecutive template closing tag example 
List<String, List<String>> MyList = 
... 

讓我們記住,我們的頭腦就像一個編譯器。人類的頭腦可以編譯這個,但以前的語法不能。 Mhhh。讓我們看看人類的頭腦是如何編譯這段代碼的。

正如你已經知道,「X」前的連續「>」和「>」標記表示一個表達式或左值。思維認爲「在表達後,兩個連續的大於符號應該成爲單個移位運算符令牌」。

併爲「串」的令牌:「兩個連續的大於符號,一個類型標識符後,應該成爲兩個連續的模板結束標記令牌」。

我覺得這種情況下不能用通常的運算符優先級處理,轉移或減少,或者只是語法,但使用(「黑客」)由分析器本身提供的一些功能。

我在您的示例語法規則中看不到錯誤。 「操作員」符號避免了混淆你提到的兩種情況。應該關注其使用移位運算符的語法和連續模板結束標記的部分。

operator_expr_example: 
    lvalue "<<" lvalue | 
    lvalue ">>" lvalue | 
    lvalue "&&" lvalue | 
; 

template_params: 
    identifier | 
    template_declaration_example | 
    array_declaration | 
    other_type_declaration 
; 

template_declaration_example: 
    identifier "<" template_params ">" 
; 

乾杯。

+0

好吧,我已經使用了操作員示例來澄清情況。考慮到「我們的大腦像一個編譯器一樣工作」,我同意,並且有一種方法可以通過使用無限的lookahead來影響語法分析。但在這種情況下,bison會在分裂堆棧解決某些衝突時推遲所有語義操作,並在恢復到確定性狀態時執行這些操作,因此當時影響語法分析爲時已晚。 – slavasav 2012-02-02 10:28:56