2016-11-19 84 views

回答

2

我找到了解決方案。你需要處理非確定性。目前還不清楚最初,但正確的解決辦法是這樣的:

inner_text = any*; 
tag_cdata = '<![CDATA[' inner_text >text_begin %text_end ']]>' %cdata_end; 

action text_begin { 
    text_begin_at = p; 
} 

action text_end { 
    text_end_at = p; 
} 

action cdata_end { 
    delegate.cdata(data.byteslice(text_begin_at, text_end_at-text_begin_at)) 
} 

從本質上講,你等到你確信你射擊的回調,使用信息,您先前捕獲的前解析一個完整的CDATA標籤。

此外,我發現Ragel中的某些形式的非確定性需要使用優先級明確處理。雖然這看起來有點難看,但它在某些情況下是唯一的解決方案。

在處理諸如(a+ >a_begin %a_end | b)*這樣的模式時,您會發現遇到的每個單個a都會調用這些事件,而不是最長的子序列。在某些情況下,可以使用最長匹配kleene星形**來解決這個模糊問題。它所做的是喜歡匹配現有的模式而不是環繞。

令我驚訝的是,這實際上也改變了事件被調用的方式。作爲一個例子,這將產生一個機器調用回調時,這是無法在一個時間緩衝不止一個字符:

%%{ 
    machine example; 

    action a_begin {} 
    action a_end {} 

    main := ('a'+ >a_begin %a_end | 'b')*; 
}%% 

產地:

Non-greedy Parser

你會發現,它調用a_begina_end每次。

與此相反,我們可以使內環和事件處理貪婪:

%%{ 
    machine example; 

    action a_begin {} 
    action a_end {} 

    main := ('a'+ >a_begin %a_end | 'b')**; 
}%% 

主要生產:

Greedy Parser

+0

是不是很奇怪,當你發現自己的解決方案一年未來和想法,我真的寫了那個!? :) – ioquatix

相關問題