爲此,您需要使用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)
感謝您的 - 我給它一個去看看我的身體情況如何。 –