From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!not-for-mail From: Matt Wette Newsgroups: gmane.lisp.guile.user Subject: regex-case Date: Sat, 06 Feb 2016 11:13:25 -0800 Message-ID: <61E420AD-70B6-4DEA-A7DD-EB123E22EFD0@verizon.net> NNTP-Posting-Host: plane.gmane.org Mime-Version: 1.0 (Mac OS X Mail 8.2 \(2104\)) Content-Type: multipart/mixed; boundary="Apple-Mail=_2B94E065-2EA1-4DA2-9366-93A955325869" X-Trace: ger.gmane.org 1454786566 3913 80.91.229.3 (6 Feb 2016 19:22:46 GMT) X-Complaints-To: usenet@ger.gmane.org NNTP-Posting-Date: Sat, 6 Feb 2016 19:22:46 +0000 (UTC) To: guile-user@gnu.org Original-X-From: guile-user-bounces+guile-user=m.gmane.org@gnu.org Sat Feb 06 20:22:37 2016 Return-path: Envelope-to: guile-user@m.gmane.org Original-Received: from lists.gnu.org ([208.118.235.17]) by plane.gmane.org with esmtp (Exim 4.69) (envelope-from ) id 1aS8RJ-0007EL-2l for guile-user@m.gmane.org; Sat, 06 Feb 2016 20:22:37 +0100 Original-Received: from localhost ([::1]:56133 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1aS8RI-0001KQ-8J for guile-user@m.gmane.org; Sat, 06 Feb 2016 14:22:36 -0500 Original-Received: from eggs.gnu.org ([2001:4830:134:3::10]:53393) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1aS8J4-0003Oh-WC for guile-user@gnu.org; Sat, 06 Feb 2016 14:14:07 -0500 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1aS8Iz-0002jX-V7 for guile-user@gnu.org; Sat, 06 Feb 2016 14:14:06 -0500 Original-Received: from vms173025pub.verizon.net ([206.46.173.25]:34553) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1aS8Iz-0002Vn-Q1 for guile-user@gnu.org; Sat, 06 Feb 2016 14:14:01 -0500 Original-Received: from vz-proxy-l003.mx.aol.com ([64.236.82.152]) by vms173025.mailsrvcs.net (Oracle Communications Messaging Server 7.0.5.32.0 64bit (built Jul 16 2014)) with ESMTPA id <0O2500MTI42DZP00@vms173025.mailsrvcs.net> for guile-user@gnu.org; Sat, 06 Feb 2016 13:13:26 -0600 (CST) X-CMAE-Score: 0 X-CMAE-Analysis: v=2.1 cv=EdU1O6SC c=1 sm=1 tr=0 a=a3t/a0oOYlYu/nGe1mf8ZA==:117 a=jFJIQSaiL_oA:10 a=O7t5bKa6BUj4IVpUV4AA:9 a=QEXdDO2ut3YA:10 a=TKo-VU87RgiKA-ieZm4A:9 a=N2M2hnRJIelaC1WBQpIA:9 a=CjuIK1q_8ugA:10 a=L9H7d07YOLsA:10 a=9cW_t1CCXrUA:10 a=s5jvgZ67dGcA:10 Original-Received: by 72.87.204.128 with SMTP id 0947adb3; Sat, 06 Feb 2016 19:13:26 GMT X-Mailer: Apple Mail (2.2104) X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 206.46.173.25 X-BeenThere: guile-user@gnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: General Guile related discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: guile-user-bounces+guile-user=m.gmane.org@gnu.org Original-Sender: guile-user-bounces+guile-user=m.gmane.org@gnu.org Xref: news.gmane.org gmane.lisp.guile.user:12368 Archived-At: --Apple-Mail=_2B94E065-2EA1-4DA2-9366-93A955325869 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset=utf-8 I have always missed the ease provided by Perl in throwing a string at a = list of regular expressions. I have thought it would be nice if the = (ice-9 regex) module would provide something comparable . So I started = work on a macro =E2=80=9Cregex-case=E2=80=9D. Code attached. Comments on syntax appreciated. =E2=80=94 Matt =3D=3D=3D test =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D (define str "foo") (regex-case str (("^([a-z]+)\\(([0-9]+)\\)$" v i) (list v i)) (("^([a-z]+)$" v) (list v "1=E2=80=9D))) =3D> (=E2=80=9Cfoo=E2=80=9D =E2=80=9C1=E2=80=9D) =3D=3D=3D syntax =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D (regex-case =20 (( =E2=80=A6) ) (( =E2=80=A6) ) (else ) Where is a string form of a regular expression, =E2=80=A6 = are variables that are bound to the matched subexpressions, and = is a list of expressions. The return is the last expression of the = matched case. =3D=3D=3D expansion =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D The example shown above expands to: (let ((t-292 (make-regexp "^([a-z]+)\\(([0-9]+)\\)$")) (t-293 (make-regexp "^([a-z]+)$"))) (cond ((regexp-exec t-292 str) =3D> (lambda (m) (let ((v (match:substring m 1)) (i (match:substring m 2))) (list v i)))) ((regexp-exec t-293 str) =3D> (lambda (m) (let ((v (match:substring m 1))) (list v "1")))))) I was thinking the above expansion has some chance (if it lives in the = regex module?) to memoize the make-regexp part during optimization. =20 If not a macro could be written to generate a match function which can = memoize the make-regexp part. (define regex-matcher foo (( =E2=80=A6)=20 =3D>=20 (define (let ((t-123 (make-regex )) =E2=80=A6) (lambda (str) = (cond ((regexp-exec t-123 str) ... --Apple-Mail=_2B94E065-2EA1-4DA2-9366-93A955325869 Content-Disposition: attachment; filename=regex-case.scm Content-Type: application/octet-stream; name="regex-case.scm" Content-Transfer-Encoding: 7bit ;; v160206b - M.Wette ;;; Copyright (C) 2016 Matthew R. Wette ;;; ;;; This library is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU Lesser General Public ;;; License as published by the Free Software Foundation; either ;;; version 3 of the License, or (at your option) any later version. (use-modules (ice-9 pretty-print)) (use-modules (ice-9 regex)) ;; helper macro for regex-case ;; (rx-let m (v ...) exp ...) => (let ((v (match:substring m 1)) ...) exp ...) (define-syntax rx-let (lambda (x) (syntax-case x () ((_ m (v ...) exp ...) (with-syntax (((i ...) ; fold (v ...) to (1 ...) (let f ((il '()) (n 1) (vl #'(v ...))) (if (null? vl) (reverse il) (f (cons n il) (1+ n) (cdr vl)))))) #'(let ((v (match:substring m i)) ...) exp ...)))))) ;; @example ;; (regex-case str ;; (("([a-z]+)" v) `(lower ,v)) ;; (("([A-Z]+)" v) `(upper ,v)) ;; (else (error "yuck"))) ;; @end example (define-syntax regex-case (lambda (x) (syntax-case x (else) ((_ str ((pat v ...) exp ...) ...) (with-syntax (((id ...) (generate-temporaries #'(pat ...)))) #'(let ((id (make-regexp pat)) ...) (cond ((regexp-exec id str) => (lambda (m) (rx-let m (v ...) exp ...))) ...)) )) ;; todo: pattern with "else" ))) (define str "foo") (write (regex-case str (("^([a-z]+)\\(([0-9]+)\\)$" v i) (list v i)) (("^([a-z]+)$" v) (list v "1")) ) ) (newline) ;; --- last line --- --Apple-Mail=_2B94E065-2EA1-4DA2-9366-93A955325869 Content-Transfer-Encoding: 7bit Content-Type: text/plain; charset=us-ascii --Apple-Mail=_2B94E065-2EA1-4DA2-9366-93A955325869--