このため、followed-by
ルールを使用する必要があります。基本的に 'a'または 's'を繰り返し一致させたいが、最後のトークンを消費する必要はありません。その後
(defn rep*? [subrule]
(rep* (conc subrule (followed-by subrule))))
rep*
の代わりに使用し、元のコードが動作するはずです:
(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*
の非欲張りバージョンを作成するために、そのコードをリファクタリングすることができます:ここでそれを行うためのコードです予想通り。 ...しかし
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*?
は私たちに、トークンのペアを与えています。これはconc
の代わりにinvisi-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)
感謝を - 私はそれをやってみると、私が乗る方法を見ていきます。 –