Gauche:SRE
leque: Gauche:Regexpの中間表現 の仕組みをつかって Gauche で SRE を使ってみようとする試み。
http://www.katch.ne.jp/~leque/software/repos/gauche-sre/
- 2006/06/06 05:39:25 PDT: Gauche 0.8.7 に対応しました。
- 2010/05/15 05:36:48 PDT: Gauche Devlog - Regexp read-write invariance の API を使って Gauche 0.9.1_pre1 で動くようにしました。
API
マクロ: (rx sre ...) -> regexp
,<expr> と ,@<expr> を展開したうえで SRE をパースし、正規表現に変換する。
gosh> (rx (+ whitespace)) #<regexp 0x1024c08> gosh> (regexp-decompile (rx "a" "b" "c")) (0 #f #\a #\b #\c) gosh> (define p (rx (submatch "b" (submatch "a")))) gosh> p #<regexp 0x10249d8> gosh> (rx (submatch "c" ,p)) #<regexp 0x1024730> gosh> (regexp-decompile (rx (submatch "c" ,p))) (0 #f (1 #f #\c #\b #\a)) gosh> (regexp-decompile (rx (submatch "c" ,@p))) (0 #f (1 #f #\c (2 #f #\b (3 #f #\a))))
手続き: (sre->regexp sre) -> regexp
SRE をパースし、正規表現に変換する。
gosh> (sre->regexp '(? whitespace)) #<regexp 0x79bbe0>
手続き: (sre-parse sre) -> AST
SRE をパースし、Gauche の正規表現の抽象構文木(Gauche:Regexpの中間表現参照)に変換する。
gosh> (sre-parse '(* whitespace)) (0 #f (rep 0 #f #[\x09-\x0d ]))
独自拡張
Gauche の正規表現に合わせて、一部 SRE の構文を拡張しています。
Gauche | 構文 |
(?:re...)*? | (*? re ...) |
(?:re...)+? | (+? re ...) |
(?:re...)?? | (?? re ...) |
(?:re...){n,}? | (>=? n re ...) |
(?:re...){n,m}? | (**? n m re ...) |
\B | nowb |
(?=re...) | (?= re ...) |
(?!re...) | (?! re ...) |
(?:re...)*+ | (*+ re ...) |
(?:re...)++ | (++ re ...) |
(?:re...)?+ | (?+ re ...) |
(?<=re...) | (?<= re ...) |
(?<!re...) | (?<! re ...) |
(?<name>re...) | (named-match name re ...) |
\n | (backref n) |
\k<name> | (backref name) |
コメント
- Wishlistに書いたら早速ですね。誰か書いているのかなぁと思っていました。ところでSREはGaucheの正規表現をすべてカバーしているわけではないですが(たとえば*?とか)、これを拡張して、文字列で書ける正規表現はすべてS式でも書けるようにするとどうでしょうか。
- とりあえず SRE の仕様にあるものを、と思っていて、そちらまで 気がまわってませんでした。時間が取れたら実装してみます。
- Shiro(2005/10/29 06:22:00 PDT): おお、すばらしい。ただ、scshでrxがマクロに なっているのは、静的な正規表現の場合コンパイル時に正規表現もコンパイルして しまえるから、という意図もあったはずです。なので、(rx ...) はコンパイルされた 正規表現を返す、となっている方が嬉しいのではないかと。 (逆に、SRE自体は単なるS式を使った文法の仕様に過ぎないので、sre->regexpに 渡すのはただのS式で構わないと思います。(sre->regexp '(? whitespace)) とか。)
- rxの返す正規表現は別のSREに埋め込むことができるので、それが<regexp>オブジェクトだと、<regexp>オブジェクトから元の表現を得る必要がありますね。あるいはコンパイルされた正規表現を別の正規表現に埋め込むことを可能にするか。
- leque(2005/10/29 07:23:48 PDT): そうなんですよね。 埋め込みをどうにかうまくあつかおうと思って、今はこんなふうになっています。
- Shiro(2005/10/29 19:05:42 PDT): あ、そうか。埋め込まれるSRE式はrxをかませた後の
ものか。でもscshのセマンティクスに倣うと、SRE中の,expは
a regexp whose body exp is a Scheme expression producing a string, character, char-set, or regexp as its value.
とあるので、Gaucheネイティブの#<regexp>の埋め込みもアリにしたいところですが、 そうなると regexp->中間表現 が必要ですね。 - leque(2005/11/02 23:51:49 PST): これって、regexp->string の場合と同じように構造体のなかに保存しておけばいいんでしょうか。
- Shiro(2005/11/03 05:11:49 PST): はい。ASTを取っておく方針で行くと 思います。その場合は基本的に上のパッチを頂きます。 (ただ、NULLはScmObjとしては不正な値なので、 SCM_NILかSCM_FALSEあたりで初期化するのと良いでしょう。)
- leque(2005/11/09 02:36:01 PST): なるほど。パッチの方に反映しておきました。
- Shiro(2005/11/09 02:42:05 PST): sre.scm共々、0.8.7でGauche本体に 取り込みたいと思います。text.sreにしようかなあ。
- CPAN をみてみると、Perl には regexp っていう階層があるみたいです。