2011-12-04 77 views
1

我試圖用fnparse解析字符串,如果它在一個單詞的末尾,我需要對字符進行不同的操作。爲此,我有這樣的規則:非貪婪分析與fnparse

(def a-or-s 
    (rep* (alt (lit \a) (lit \s)))) 

(def ends-with-s 
    (conc a-or-s (lit \s))) 

我嘗試匹配字符串「aas」。然而,這並不解析,因爲rep*是貪婪的並且吞下該單詞的最後一個字符,並且conc規則不起作用。我怎樣才能繞過這個並正確地匹配這些結構?

回答

1

爲此,您需要使用followed-by規則,基本上,您希望重複匹配'a'或's',但不消耗最後一個標記。下面的代碼做到這一點:

(def a-or-s 
    (lit-alt-seq "as")) ;; same as (alt (lit \a) (lit \s)) 

(def ends-with-s 
    (conc 
    (rep* (conc a-or-s (followed-by a-or-s))) 
    (lit \s))) 

我們可以重構代碼創建的rep*非貪婪的版本是這樣的:

(defn rep*? [subrule] 
    (rep* (conc subrule (followed-by subrule)))) 

然後使用它,而不是rep*和你原來的代碼應工作如預期。嘗試它雖然...

user> (rule-match (conc (rep*? a-or-s) (lit \s)) identity #(identity %2) {:remainder "aaaaaaaasss"}) 
([(\a \a) (\a \a) (\a \a) (\a \a) (\a \a) (\a \a) (\a \a) (\a \s) (\s \s) (\s \s)] \s) 

之後......你可能會問「發生了什麼輸出?」,以及rep*?給我們提供了對令牌的,因爲這是我們提出的要求。這可以通過使用invisi-conc代替conc固定:

(defn rep*? [subrule] 
    (rep* (invisi-conc subrule (followed-by subrule)))) 

user> (rule-match (conc (rep*? a-or-s) (lit \s)) identity #(identity %2) {:remainder "aaaaaaaasss"}) 
([\a \a \a \a \a \a \a \a \s \s] \s) 
+0

感謝您的 - 我給它一個去看看我的身體情況如何。 –