2013-04-30 53 views
2

,以供參考,在這裏是我的代碼:http://hpaste.org/86949哈斯克爾:秒差距鬧掰出來的圖案

我試圖解析以下表達式:if (a[1].b[2].c.d[999].e[1+1].f > 3) { }。調用的方法是varExpr,它解析可變成員鏈。

語境

在我解析語言,一個點可以指定訪問一個成員變量。由於成員變量可以是另一個對象,所以可以生成鏈,即:a.b.c,或者本質上爲(a.b).c。不要以爲這些點是功能組成。

實施

的邏輯是這樣的:

  • 首先,before <- many vocc收集的varname .所有實例和它們的可選的陣列表達,只留下單個標識符左

  • this <- vtrm收集剩餘的標識符和數組表達式 - 唯一一個沒有進入點

問題

我有兩個問題:

首先,第一項[是有原因的,我不能確定],似乎總是需要將其包裹在括號內爲解析器接受它,即:(a[1]).b[2].c... - 後續術語不需要這個。其次,many vocc不會停止解析。它總是期望另一個標識符和另一個點,我無法終止表達式來捕獲最後的vtrm

我在尋找能夠幫助我解決問題/頭痛的提示或解決方案。謝謝。

回答

4

varExpr運行時,它會檢查下一位輸入是否與voccvtrm匹配。

varExpr = do before <- many vocc -- Zero or more occurrences 
      this <- vtrm 
      return undefined 

的問題是,由vtrm匹配任何輸入端還通過vocc第一步匹配。當varExpr運行時,它運行vocc,其運行vobj,其運行vtrm。當vocc失敗而不消耗輸入

vocc = vobj <* symbol "." 
vobj = choice [try vtrm, try $ parens vtrm] 

many vocc解析結束。當vtrmparens vtrm都失敗時會發生這種情況。但是,在many vocc結束後,要運行的下一個分析程序是vtrm,並且此分析程序肯定會失敗!

如果在輸入中未找到".",您希望vocc在不消耗輸入的情況下發生故障。爲此,您需要使用try

vocc = try $ vobj <* symbol "." 

另外,如果vobjvtrm確實應該是相同的語法,您可以定義爲varExpr vobj `sepBy1` symbol "."

+0

工作過的魅力!任何想法爲什麼第一學期總是需要它的附屬物? – kvanberendonck 2013-05-01 02:15:16

+1

當我自己測試'varExpr'時,第一項不需要括號。我猜''varExpr'和'callExpr'之間有重疊,類似於'vocc'和'vtrm'之間的重疊。試着用'callExpr'使用'try'。 – Heatsink 2013-05-01 02:36:59