Gauche では正規表現を一旦 S 式による中間表現に変換してから 正規表現コンパイラに渡す。こうすることにより、正規表現の最適化部分を リスト処理で書いたり、SRE のような別の構文をサポートすることが 容易になっている。
中間表現の構文は以下の通り(GHG:regexp.c)。
<ast> : (<element> ...) <element> : <clause> ; special clause | <item> ; matches <item> <item> : <char> ; matches char | <char-set> ; matches char set | (comp . <char-set>) ; matches complement of char set | any ; matches any char | bol | eol ; beginning/end of line assertion | wb | nwb ; word-boundary/negative word boundary assertion <clause> : (seq . <ast>) ; sequence | (seq-uncase . <ast>) ; sequence (case insensitive match) | (seq-case . <ast>) ; sequence (case sensitive match) | (alt . <ast>) ; alternative | (rep . <ast>) ; 0 or more repetition of <ast> (greedy) | (rep-min . <ast>) ; 0 or more repetition of <ast> (lazy) | (rep-bound <n> . <ast>) ; repetition up to <n> (greedy) | (rep-bound-min <n> . <ast>) ; repetition up to <n> (lazy) | (rep-while . <ast>) ; like rep, but no backtrack | (<integer> . <ast>) ; capturing group | (assert . <ast>) ; positive look-ahead assertion | (nassert . <ast>) ; negative look-ahead assertion
手続き regexp-parse で文字列をパースすると中間表現が得られる。
gosh> (regexp-parse "abc*(def)+[xyz]*") (0 #\a #\b (rep #\c) (seq #0=(1 #\d #\e #\f) (rep #0#)) (rep #[x-z]))
この中間表現は regexp-optimize で最適化し、 regexp-compile により regexp オブジェクトに変換することができる。
gosh> (regexp-optimize '(0 #\a #\b (rep #\c) (seq #0=(1 #\d #\e #\f) (rep #0#)) (rep #[x-z]))) (0 #\a #\b (rep-while #\c) #0=(1 #\d #\e #\f) (rep #0#) (rep-while #[x-z])) gosh> (regexp-compile '(0 #\a #\b (rep-while #\c) #0=(1 #\d #\e #\f) (rep #0#) (rep-while #[x-z]))) #<regexp 0x98a9b90>
Tag: 正規表現