From unknown Fri Jun 20 19:54:56 2025 X-Loop: don@donarmstrong.com Subject: bug#192: regexp does not work as documented Reply-To: Bruno Haible , 192@debbugs.gnu.org Resent-From: Bruno Haible Original-Sender: bug-gnu-emacs-bounces+monnier=iro.umontreal.ca@gnu.org Resent-To: bug-submit-list@lists.donarmstrong.com Resent-CC: Emacs Bugs Resent-Date: Tue, 06 May 2008 03:35:03 +0000 Resent-Message-ID: Resent-Sender: don@donarmstrong.com X-Emacs-PR-Message: report 192 X-Emacs-PR-Package: emacs X-Emacs-PR-Keywords: Received: via spool by submit@emacsbugs.donarmstrong.com id=B.121004457618364 (code B ref -1); Tue, 06 May 2008 03:35:03 +0000 X-Spam-Checker-Version: SpamAssassin 3.2.3-bugs.debian.org_2005_01_02 (2007-08-08) on rzlab.ucr.edu X-Spam-Level: ** X-Spam-Status: No, score=2.3 required=4.0 tests=CT_IMAGE,FOURLA, IMPRONONCABLE_1,MURPHY_WRONG_WORD2 autolearn=no version=3.2.3-bugs.debian.org_2005_01_02 Received: (at submit) by emacsbugs.donarmstrong.com; 6 May 2008 03:29:36 +0000 Received: from mercure.iro.umontreal.ca (mercure.iro.umontreal.ca [132.204.24.67]) by rzlab.ucr.edu (8.13.8/8.13.8/Debian-3) with ESMTP id m463TPjq018358 for ; Mon, 5 May 2008 20:29:27 -0700 Received: by mercure.iro.umontreal.ca (Postfix, from userid 20848) id 107E52CFA13; Mon, 5 May 2008 23:29:24 -0400 (EDT) X-Original-To: monnier@iro.umontreal.ca Received: from pinpin.iro.umontreal.ca (pinpin.iro.umontreal.ca [132.204.24.52]) by mercure.iro.umontreal.ca (Postfix) with ESMTP id A4ED22CFA13 for ; Mon, 5 May 2008 23:29:24 -0400 (EDT) Received: from lists.gnu.org (lists.gnu.org [199.232.76.165]) by pinpin.iro.umontreal.ca (Postfix) with ESMTP id 25F193B8B43 for ; Mon, 5 May 2008 23:28:45 -0400 (EDT) Received: from localhost ([127.0.0.1]:34040 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1JtDr5-0007C0-9R for monnier@iro.umontreal.ca; Mon, 05 May 2008 23:28:39 -0400 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1JtC1F-0003sm-6f for bug-gnu-emacs@gnu.org; Mon, 05 May 2008 21:31:01 -0400 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1JtC19-0003sa-Im for bug-gnu-emacs@gnu.org; Mon, 05 May 2008 21:30:59 -0400 Received: from [199.232.76.173] (port=60645 helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1JtC19-0003sX-B7 for bug-gnu-emacs@gnu.org; Mon, 05 May 2008 21:30:55 -0400 Received: from mo-p07-ob.rzone.de ([81.169.146.188]) by monty-python.gnu.org with esmtp (Exim 4.60) (envelope-from ) id 1JtC17-0005rO-M1 for bug-gnu-emacs@gnu.org; Mon, 05 May 2008 21:30:55 -0400 X-RZG-CLASS-ID: mo07 X-RZG-AUTH: gMysVb8JT2gB+rFDu0PuvnvUUGmhfq1rhHRG5dSek381RH36MmEbn1EK Received: from linuix.haible.de (dslb-084-058-085-077.pools.arcor-ip.net [84.58.85.77]) by post.webmailer.de (fruni mo7) (RZmta 16.34) with ESMTP id 6014fak45KXXEt ; Tue, 6 May 2008 03:30:48 +0200 (MEST) (envelope-from: ) From: Bruno Haible To: bug-gnu-emacs@gnu.org Date: Tue, 6 May 2008 03:30:45 +0200 User-Agent: KMail/1.5.4 MIME-Version: 1.0 Content-Type: Multipart/Mixed; boundary="Boundary-00=_FT7HID3WnMEP223" Message-Id: <200805060330.45156.bruno@clisp.org> X-detected-kernel: by monty-python.gnu.org: Solaris 10 (beta) X-Mailman-Approved-At: Mon, 05 May 2008 23:27:16 -0400 X-BeenThere: bug-gnu-emacs@gnu.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "Bug reports for GNU Emacs, the Swiss army knife of text editors" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: bug-gnu-emacs-bounces+monnier=iro.umontreal.ca@gnu.org Errors-To: bug-gnu-emacs-bounces+monnier=iro.umontreal.ca@gnu.org X-DIRO-MailScanner-Information: Please contact the ISP for more information X-DIRO-MailScanner: Found to be clean X-DIRO-MailScanner-SpamCheck: n'est pas un polluriel, SpamAssassin (score=0.05, requis 5, BAYES_00 -2.60, CTYPE_F_IMAGE 1.99, RECEIVED_FROM_NOUNK 0.66, SPF_HELO_PASS -0.00) X-DIRO-MailScanner-From: bug-gnu-emacs-bounces+monnier=iro.umontreal.ca@gnu.org --Boundary-00=_FT7HID3WnMEP223 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Content-Disposition: inline The regular expression (as an Emacs string) "^msgstr\\(\\[[0-9]\\]\\)?.*\n\\(\".*\n\\)*" is supposed to search for a line starting with "msgstr" and an optional digit inside brackets, followed by as many lines starting with a double-quote as possible. The Emacs documentation says: "The matcher processes a `*' construct by matching, immediately, as many repetitions as can be found." This is apparently not the case with the above regexp. ---------------------------------------------------------------------------- To reproduce: $ emacs fr.po or $ emacs -nw fr.po Leave the cursor at the beginning of the file. M-x highlight-regexp Regexp to highlight (enter this with Ctrl-Q Ctrl-J for each of the two newlines): ^msgstr\(\[[0-9]\]\)?.* \(".* \)* Highlight using face: hi-yellow Then move around in the buffer and look which lines are highlighted. In the first match already, only 5 out of 11 lines are highlighted. Then, line 300 (in emacs 22) or line 335 (in emacs 21) are not highlighted either. The attached screenshots were produced with emacs-22.2.1 (on i686-pc-linux-gnu) and with emacs-21.2.1 (on powerpc-apple-darwin7.9.0). ---------------------------------------------------------------------------- In GNU Emacs 22.2.1 (i686-pc-linux-gnu, X toolkit, Xaw3d scroll bars) of 2008-05-01 on linuix Windowing system distributor `The XFree86 Project, Inc', version 11.0.40300001 configured using `configure '--prefix=/packages/gnu'' Important settings: value of $LC_ALL: nil value of $LC_COLLATE: POSIX value of $LC_CTYPE: nil value of $LC_MESSAGES: nil value of $LC_MONETARY: nil value of $LC_NUMERIC: nil value of $LC_TIME: nil value of $LANG: de_DE.UTF-8 locale-coding-system: utf-8 default-enable-multibyte-characters: t Major mode: Lisp Interaction Minor modes in effect: tooltip-mode: t tool-bar-mode: t mouse-wheel-mode: t menu-bar-mode: t file-name-shadow-mode: t global-font-lock-mode: t font-lock-mode: t blink-cursor-mode: t unify-8859-on-encoding-mode: t utf-translate-cjk-mode: t auto-compression-mode: t line-number-mode: t Recent input: Recent messages: ("emacs") Loading cl-indent...done Loading derived...done For information about GNU Emacs and the GNU system, type C-h C-a. Loading emacsbug... Loading regexp-opt...done Loading emacsbug...done PS: Where is the bug tracker? I don't see it at https://savannah.gnu.org/projects/emacs --Boundary-00=_FT7HID3WnMEP223 Content-Type: image/png; name="emacs21-1.png" Content-Transfer-Encoding: base64 Content-Disposition: inline; filename="emacs21-1.png" iVBORw0KGgoAAAANSUhEUgAAAf0AAANtCAMAAACt61LQAAAABGdBTUEAALGPC/xhBQAAAQtQTFRF AAAAAM0ABS9EBgYGBz9bCE9yCl+JDAwMD47NESEoFDNDFjVFFxcXGhoaHh4eHi41Hx8fHy82H05m IE9nIVBoIiIiIyMjJCQkJSUlJiYmJ1ZuJ2eHKCgoKSkpLDxDLS0tLT1ELj5FLy8vMTExMjIyNDQ0 NlVlNzc3N1ZmOllpPT09Pj4+Pz8/P26GQUFBQWBwRERERUVFSkpKS0tLTExMTU1NTk5OUFBQUWFo U1NTVVVVVlZWV1dXWlpaXFxcYGBgY2Njbm5ucHBwc3Nzc4OKdnZ2eHh4eXl5fIyToKCgpqamrKys srKyt7e3ubm5v7+/xsbGzMzMzc0A0tLS2dnZ3Nzc39/f//vt////ubGKGwAAADh0RVh0U29mdHdh cmUAWFYgVmVyc2lvbiAzLjEwYSAgUmV2OiAxMi8yOS85NCAoUE5HIHBhdGNoIDEuMindFS5JAAAg AElEQVR4nO19CcM0PVbVLVQE3BFEHRcQQRQ/BBU33MYdGWepYTT//5f4Pl2V5NwlW1Vv1bnnfbue 6tTNTSonJ5Wlu0PkmBm/4PgA/FwYx/e/2P95x/Xxcz8bx87+9wRefSuOYfzcz/6YI7TeZ/b/xa/9 1t+N1P+3P/+3H5XFX/D/j/r/jf3/xBBa7zP73/2NP/r7v76R/9d/9bcfp/0/6/8f9P+LfXik//EX 2/X30PL/zn/9vd//7S/yv/vvfy+2/ETbH8ZfCN1Uf6Vyt3rjqOPG/v9N2Niuvsfn/m/869/6y999 +/tX/mF67lP4Ip6Osr9VsnveoaOMG/t/mrCx/adxXBff/yl9XaTbddbr+/f/8Q9/93vf+19/6ztg P3y7HDb2v3j89toJTX9+fgsKhtD3GIhXPxw/+P+N/Z8mbGz/NLIP73/60/09Y/+7X/3D3/+DX/mb t+Z/ky196yd++5fYzyRHWSfegyV0Q/qvfz5+6v8b+z/5yU++uP72Z2P7J7fzr+P+/idbZbhd5yO+ 3/lHf+a7f7V1/bYxAWMf5P7tgNJmJ8kWY3jz/3jc2P/xj3/8Re63PxvbP76dfx3393ids/8rv/bb f+0/f3c73duLrwrw7d/mficxS7/EfmCWGOJ4HG7s/+hHP/ri7dufje0f3c6/jvt7vM5b/v/56//4 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 --Boundary-00=_FT7HID3WnMEP223 Content-Type: image/png; name="emacs22-2.png" Content-Transfer-Encoding: base64 Content-Disposition: inline; filename="emacs22-2.png" iVBORw0KGgoAAAANSUhEUgAAAf0AAANtCAMAAACt61LQAAAABGdBTUEAALGPC/xhBQAAAQ5QTFRF AAAAAP//BS9EBgYGBz9bCE9yCl+JDAwMD47NESEoFDNDFjVFFxcXGhoaHh4eHi41Hx8fHy82H05m IE9nIVBoIiIiIyMjJCQkJSUlJiYmJ1ZuJ2eHKCgoKSkpLDxDLS0tLT1ELj5FLy8vMTExMjIyNDQ0 NlVlNzc3N1ZmOllpPT09Pj4+Pz8/P26GQUFBQWBwRERERUVFSkpKS0tLTExMTU1NTk5OUFBQUWFo U1NTVVVVVlZWV1dXWlpaXFxcYGBgY2Njbm5ucHBwc3Nzc4OKdnZ2eHh4eXl5fIyToKCgpqamrKys srKyt7e3ubm5v7+/xsbGzMzMzQAAzQDNzc0A0tLS2dnZ3Nzc39/f////wzvzkAAAADh0RVh0U29m dHdhcmUAWFYgVmVyc2lvbiAzLjEwYSAgUmV2OiAxMi8yOS85NCAoUE5HIHBhdGNoIDEuMindFS5J AAAgAElEQVR4nO19iaP9vFbVvqgIOCOIigOIIIofgorz9JwRfI/3tY9n//9/xN9pM6w9JE3anLF7 3Xt7ejLs7GRlpWlyzi2R48r4OccH4GeWfvzgxv7POt4fP/PTfgT2f1Xg2VVxdONnfvqHHMve+8z+ v/iV3/y7kfr//uf/9r1c/Dn/vdfvN/b/M8Oy9z6z/93f+Pd//9c28v/6L//W/bT/Z/33Tr839uGS /oc3tuvvYeT/7f/2u7/3Wzfyv/sffy+O/ETbC+NvWRqJDsUM7DqOClb2/1/Cxnb1PV73f/1f/+Zf /u7b61/5h+m6T8uNeHL23wEr+3+asLH9p/G+Lr7/U7pF0hrPZn3/4T/9we/86q/+77/1HbC/fIte NvZvPH77C4Sml5/dglKEgAh79sXxg39X9n+SsLH9k8g+vP/JT8J7xv53v/wHv/f7v/Q31+F/ky19 myd++0nsZ5KjrBPvBaGrkOdfHz/1d2X/xz/+8Y3rby8b2z9ez2/H8P7HW2dY4/kd32//oz/z3b/a pn7bPQFjH+T+7ZAHA3GS0mbyffh/BFb2/+RP/uRG7reXje0/Wc9vx/Ae4zn7v/Qrv/XX/st362kY L24d4NvPZh4YXbL2f1aznweB/Ood4N5Y2f/Rj3504+3by8b2j9bz2zG8x3g+8v+vX/vH//Of/tXv 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 +4X2xF6q0oYdQ+YqVfIa7KOFDXM8mOwry5JN9EoMEFyOslxWC10wl7jFPnpisU+svg3sn9T+Eule +T7EfiEdNKTBfnJD5LW1L6o52yN/ySsertsdzomnLyvdDGHNc5j9gm/E+lfJE8S+9vOl/4bqyC+q Vx6jdN1yO6QYYu9EHY2RH7yZ46z/9ggCITnLKxFOi5EmtC1ZdhRMCRbVStyTFvbNVtUjke7iDHXt R6bZ3M+a9RmzDjVLSSkJ0se8aZ6D5zlW1TG0AJ+tJUThb1N/Ji3bq4XbIatGhIORXW6xpVkdWV1y rTEjpmfHhYVQNk+Y3fTCWJNpvd+3Rvs3gU3PB4Krz47naL7f/1KDvePV0P1ZSn8m13Xhz+S6MoZp nz9S0/EWOKh9zbGz/4Y4qH1n/yNQ1358mLL1dNqVauf6rVHXPj4RWz7PenuqsdP/ztjRfnqeunh6 ej443hgt2p/Zs+v5ieOd0aL9pHrCkd8neO+PPe1H3rfU+dyv+Z+A9vv9NOA7PgYd9/vk93efBl/n fwzW/08+6fPnwvf4HoPXZ9/QPqXJfhlm5NCLhG2sNO88c4EyVrD3rbEUhfSZcaqwf7dLa+EGbUf7 fHGvaNoOK+Qh9tLkuh1auuesWt4p1trA2ANV3kUkxqmmfZW3uzuQfd7Afkn7R9nvSH4ExQWHM+wf ybDHPoHeb7HbueX+efaLLh7RfvIh3umHnR12LQgLADkkbAKFnQFzh0isHlO2FVcS1rOcyyiXrUDy YG4T7Qg/xY4VtdWOe0gsl04Pel9D07moNdrX3rJSCv4Ya/JVNM35k/YjN7zNyXhNf5CeDyM5FVrj 6WGPqVBuiX1mE+zIxJb9eimYRu+C2aVnvc/zDOMAr7W2j95mm1T0x/agjD7tw6ova8GZdVPtAaW8 2SlgX+VlbQt5WZ1IhaANZrPAPtQI/dS1Iy5C8LPAvijd1D6yD7VgPmj2tYfEShZ/dbRrX+jC6JUV 9uHIXkgRMmNZeWZnsk917WPCspoY+xhVsJbMUF37rHjjug/kq9azCi63P7ZDbtWx2o/1ZT6gmzXt Yy6SfuqeY7etTMn2n6u9kVTpsVqUrvtGCxesSe5t9tECGXN+MsootdUaHv0kstOnMeAY+yXt53ka jPzgeo7ljsLVjM+L8DzHGm2by2J2YkooF8mX8yLuM/Oc9SsrbzFkzhwZ8zG1QlK/32c10G3FPay1 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 TkSuQmCC --Boundary-00=_FT7HID3WnMEP223 Content-Type: image/png; name="emacs21-2.png" Content-Transfer-Encoding: base64 Content-Disposition: inline; filename="emacs21-2.png" iVBORw0KGgoAAAANSUhEUgAAAf0AAANtCAMAAACt61LQAAAABGdBTUEAALGPC/xhBQAAAQtQTFRF AAAAAM0ABS9EBgYGBz9bCE9yCl+JDAwMD47NESEoFDNDFjVFFxcXGhoaHh4eHi41Hx8fHy82H05m IE9nIVBoIiIiIyMjJCQkJSUlJiYmJ1ZuJ2eHKCgoKSkpLDxDLS0tLT1ELj5FLy8vMTExMjIyNDQ0 NlVlNzc3N1ZmOllpPT09Pj4+Pz8/P26GQUFBQWBwRERERUVFSkpKS0tLTExMTU1NTk5OUFBQUWFo U1NTVVVVVlZWV1dXWlpaXFxcYGBgY2Njbm5ucHBwc3Nzc4OKdnZ2eHh4eXl5fIyToKCgpqamrKys srKyt7e3ubm5v7+/xsbGzMzMzc0A0tLS2dnZ3Nzc39/f//vt////ubGKGwAAADh0RVh0U29mdHdh cmUAWFYgVmVyc2lvbiAzLjEwYSAgUmV2OiAxMi8yOS85NCAoUE5HIHBhdGNoIDEuMindFS5JAAAg AElEQVR4nO19CaPsPHJVOUBIwh4SAgxLQkgIhC8kQNjCNuwhwyyeDPj//xLebVvSqUVSqe3udrfr vHf7uuVSVamOSpal7muiwJXxC4EPwM8t4/j+F/s/H3h//NzPxrGx/z2BVzclMIyf+9kfcyy994X9 f/Frv/V3E/X/7c//7Ue5+Avx/1H/v7H/nxiW3vvC/nd/44/+/q+v5P/1X/3tx+X+n43/D/r/xT5c 0v/4i+32exj5f+e//t7v//YX+d/997+XRn6i9Rfjb1ncVH9ZOazfBNq4sf9/M1a2m+/xuv8b//q3 /vJ3337/lX+Yr/u0fBFP97K/drIjWxio48b+n2asbP9puq9L7/+Uvk7S7Tyb9f37//iHv/u97/2v v/UdsL98O72s7H/x+O1nIzT/+vm1aDESfauBePXF8YP/39j/acbK9k8T+/D+pz/d3jP2v/vVP/z9 P/iVv3kb/te0pW/zxG//MvuF5JTWmffFSnQj9V9/ffzU/zf2f/KTn3xx/e3XyvZPbsdfr9v7n6yd 4Xae3/H9zj/6M9/9q3Xqt94TMPYh3b+9YGqzgyyLNWL4fzxu7P/4xz/+Ivfbr5XtH9+Ov16393ie s/8rv/bbf+0/f3c73MaLrw7w7d+qfiOxpH6N/YVJYkngcbix/6Mf/eiLt2+/VrZ/dDv+et3e43k+ 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 --Boundary-00=_FT7HID3WnMEP223 Content-Type: image/png; name="emacs22-1.png" Content-Transfer-Encoding: base64 Content-Disposition: inline; filename="emacs22-1.png" iVBORw0KGgoAAAANSUhEUgAAAf0AAANtCAMAAACt61LQAAAABGdBTUEAALGPC/xhBQAAAQ5QTFRF AAAAAP//BS9EBgYGBz9bCE9yCl+JDAwMD47NESEoFDNDFjVFFxcXGhoaHh4eHi41Hx8fHy82H05m IE9nIVBoIiIiIyMjJCQkJSUlJiYmJ1ZuJ2eHKCgoKSkpLDxDLS0tLT1ELj5FLy8vMTExMjIyNDQ0 NlVlNzc3N1ZmOllpPT09Pj4+Pz8/P26GQUFBQWBwRERERUVFSkpKS0tLTExMTU1NTk5OUFBQUWFo U1NTVVVVVlZWV1dXWlpaXFxcYGBgY2Njbm5ucHBwc3Nzc4OKdnZ2eHh4eXl5fIyToKCgpqamrKys srKyt7e3ubm5v7+/xsbGzMzMzQAAzQDNzc0A0tLS2dnZ3Nzc39/f////wzvzkAAAADh0RVh0U29m dHdhcmUAWFYgVmVyc2lvbiAzLjEwYSAgUmV2OiAxMi8yOS85NCAoUE5HIHBhdGNoIDEuMindFS5J AAAgAElEQVR4nO19CYP8PnKVZoGQhDskBFiOhJAQCP+QAOG+ljtk2aPtzaLv/0X4dVvHq0OyZLu7 7Va9mXG7pVJJ1lPp7OlyzjAyftHwAfie78cP7uz/guH6+N7P+xHY/z7Dux/F0I3v/fyPKfza+8z+ v/j13/67kfr//uf/9rOK+Iv2+6zfb+z/ZwK/9j6z/93f+Pd//zcW8v/6r/3O82z/z9rvk37v7MOQ /sd3tuvvoef/3f/2+3/wO3fyv/sffy/2/M4tL4Q/7xuJDtkc2HQMFTzY/38JC9vV9zju/+a//u2/ /N2317/yD9O47/ydeGfsXwEP9v80YWH7T+O6Lr7/U3ePdI94Muv7D//pj37v+9//33/rO2Dff4v2 C/t3Hr/9BULTyy8sQSmCgYW9e3D84N8H+z9LWNj+WWQf3v/sZ+E9Yf+7X/ujP/jDX/2bj+5/MVv3 bZ747Sexn0mOZp14Lxi6CHn/+Pipvw/2f/rTn965/vaysP3Tx/39Gt7/dGkMj3i64vvdf/RnvvtX y9RvWRMQ9sHcv11yZ8Bukmwm37r/V+DB/k9+8pM7ud9eFrZ/8ri/X8N7jKfs/+qv/85f+y/fPW5D f3FvAN9+FvXAqM+2/wuS/dwJ5FdrAM/Gg/0f//jHd96+vSxs//hxf7+G9xhPe/7/9Rv/+H/+07/6 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 QmCC --Boundary-00=_FT7HID3WnMEP223 Content-Type: application/x-gzip; name="fr.po.gz" Content-Transfer-Encoding: base64 Content-Disposition: attachment; filename="fr.po.gz" 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 AA== --Boundary-00=_FT7HID3WnMEP223-- From unknown Fri Jun 20 19:54:56 2025 X-Loop: don@donarmstrong.com Subject: bug#192: regexp does not work as documented Reply-To: Chong Yidong , 192@debbugs.gnu.org Resent-From: Chong Yidong Resent-To: bug-submit-list@lists.donarmstrong.com Resent-CC: Emacs Bugs Resent-Date: Tue, 06 May 2008 04:35:03 +0000 Resent-Message-ID: Resent-Sender: don@donarmstrong.com X-Emacs-PR-Message: report 192 X-Emacs-PR-Package: emacs X-Emacs-PR-Keywords: Received: via spool by 192-submit@emacsbugs.donarmstrong.com id=B192.12100479176030 (code B ref 192); Tue, 06 May 2008 04:35:03 +0000 X-Spam-Checker-Version: SpamAssassin 3.2.3-bugs.debian.org_2005_01_02 (2007-08-08) on rzlab.ucr.edu X-Spam-Level: X-Spam-Status: No, score=0.6 required=4.0 tests=AWL,FOURLA,IMPRONONCABLE_1, MURPHY_WRONG_WORD2 autolearn=no version=3.2.3-bugs.debian.org_2005_01_02 Received: (at 192) by emacsbugs.donarmstrong.com; 6 May 2008 04:25:17 +0000 Received: from cyd.mit.edu (CYD.MIT.EDU [18.115.2.24]) by rzlab.ucr.edu (8.13.8/8.13.8/Debian-3) with ESMTP id m464PDqR005814 for <192@emacsbugs.donarmstrong.com>; Mon, 5 May 2008 21:25:14 -0700 Received: by cyd.mit.edu (Postfix, from userid 1000) id 7245D4E304; Tue, 6 May 2008 00:20:31 -0400 (EDT) From: Chong Yidong To: emacs-devel@gnu.org Cc: 192@debbugs.gnu.org, koppel@ece.lsu.edu, Bruno Haible Date: Tue, 06 May 2008 00:20:31 -0400 Message-ID: <87k5i8ukq8.fsf@stupidchicken.com> MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable > $ emacs fr.po > M-x highlight-regexp > > Regexp to highlight (enter this with Ctrl-Q Ctrl-J for each of the two > newlines): > > ^msgstr\(\[[0-9]\]\)?.* > \(".* > \)* > > Highlight using face: hi-yellow > > Then move around in the buffer and look which lines are highlighted. > In the first match already, only 5 out of 11 lines are highlighted. I believe this bug arises because highlight-regexp uses font-lock to highlight the regular expression, and the font-lock engine is intentionally limiting the region to search for the multi-line regular expression. OTOH, I don't see what we can do about this problem. Maybe we could add a note to the docstring of highlight-regexp saying that multi-line regular expressions are problematic? Does anyone have a suggestion? BTW, here is a simplified recipe, for those who didn't download the attached file: 1. Copy the following text, between the "---...----" lines, into a buffer ------------------ # Messages fran=C3=A7ais pour GNU gettext. # Copyright =C2=A9 2006 Free Software Foundation, Inc. # Fran=C3=A7ois Pinard , 1996. # # msgid "" msgstr "" "Project-Id-Version: GNU gettext-tools 0.16.2-pre5\n" "Report-Msgid-Bugs-To: bug-gnu-gettext@gnu.org\n" "POT-Creation-Date: 2007-11-02 03:23+0100\n" "PO-Revision-Date: 2007-10-27 13:35+0200\n" "Last-Translator: Christophe Combelles \n" "Language-Team: French \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=3DUTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=3D2; plural=3D(n > 1);\n" ------------------ 2. M-: (highlight-regexp "^m.*\n\\(\".*\n\\)+") RET Note that the last two lines remain unhighlighted. From unknown Fri Jun 20 19:54:56 2025 X-Loop: don@donarmstrong.com Subject: bug#192: regexp does not work as documented Reply-To: Bruno Haible , 192@debbugs.gnu.org Resent-From: Bruno Haible Resent-To: bug-submit-list@lists.donarmstrong.com Resent-CC: Emacs Bugs Resent-Date: Tue, 06 May 2008 11:45:04 +0000 Resent-Message-ID: Resent-Sender: don@donarmstrong.com X-Emacs-PR-Message: report 192 X-Emacs-PR-Package: emacs X-Emacs-PR-Keywords: Received: via spool by 192-submit@emacsbugs.donarmstrong.com id=B192.121007372324786 (code B ref 192); Tue, 06 May 2008 11:45:04 +0000 X-Spam-Checker-Version: SpamAssassin 3.2.3-bugs.debian.org_2005_01_02 (2007-08-08) on rzlab.ucr.edu X-Spam-Level: * X-Spam-Status: No, score=1.8 required=4.0 tests=AWL,FOURLA,IMPRONONCABLE_1, MURPHY_WRONG_WORD2 autolearn=no version=3.2.3-bugs.debian.org_2005_01_02 Received: (at 192) by emacsbugs.donarmstrong.com; 6 May 2008 11:35:23 +0000 Received: from mo-p07-ob.rzone.de (mo-p07-ob.rzone.de [81.169.146.190]) by rzlab.ucr.edu (8.13.8/8.13.8/Debian-3) with ESMTP id m46BZIrI024780 for <192@emacsbugs.donarmstrong.com>; Tue, 6 May 2008 04:35:20 -0700 X-RZG-CLASS-ID: mo07 X-RZG-AUTH: gMysVb8JT2gB+rFDu0PuvnvUUGmhfq1rhHRG5dSek381RH36PlIq8YOI Received: from linuix.haible.de (dslb-084-058-049-074.pools.arcor-ip.net [84.58.49.74]) by post.webmailer.de (fruni mo55) (RZmta 16.34) with ESMTP id y00dfak469QrFI ; Tue, 6 May 2008 13:35:15 +0200 (MEST) (envelope-from: ) From: Bruno Haible To: Chong Yidong , emacs-devel@gnu.org Date: Tue, 6 May 2008 13:35:11 +0200 User-Agent: KMail/1.5.4 Cc: 192@debbugs.gnu.org, koppel@ece.lsu.edu References: <87k5i8ukq8.fsf@stupidchicken.com> In-Reply-To: <87k5i8ukq8.fsf@stupidchicken.com> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 8bit Content-Disposition: inline Message-Id: <200805061335.11379.bruno@clisp.org> Chong Yidong wrote: > BTW, here is a simplified recipe, for those who didn't download the > attached file: > > 1. Copy the following text, between the "---...----" lines, into a > buffer > > ------------------ > # Messages français pour GNU gettext. > # Copyright © 2006 Free Software Foundation, Inc. > # François Pinard , 1996. > # > # > msgid "" > msgstr "" > "Project-Id-Version: GNU gettext-tools 0.16.2-pre5\n" > "Report-Msgid-Bugs-To: bug-gnu-gettext@gnu.org\n" > "POT-Creation-Date: 2007-11-02 03:23+0100\n" > "PO-Revision-Date: 2007-10-27 13:35+0200\n" > "Last-Translator: Christophe Combelles \n" > "Language-Team: French \n" > "MIME-Version: 1.0\n" > "Content-Type: text/plain; charset=UTF-8\n" > "Content-Transfer-Encoding: 8bit\n" > "Plural-Forms: nplurals=2; plural=(n > 1);\n" > ------------------ > > 2. M-: (highlight-regexp "^m.*\n\\(\".*\n\\)+") RET > > Note that the last two lines remain unhighlighted. Yes. I reproduce with this simpler recipe as well. Thank you. > I believe this bug arises because highlight-regexp uses font-lock to > highlight the regular expression, and the font-lock engine is > intentionally limiting the region to search for the multi-line regular > expression. You are right that there is a limit, but it is set to 200000: highlight-regexp is aliased to hi-lock-face-buffer, which asks for the arguments and calls hi-lock-set-pattern. hi-lock-set-pattern does little more than applying a margin of 100000 and calling re-search-forward. I believe the origin of the bug is deeper, because - the limit of 100000 is way larger than the little snippet you posted, - I originally observed the bug in po-mode (part of GNU gettext), in a function po-find-span-of-entry which essentially only calls re-search-backward and re-search-forward. > OTOH, I don't see what we can do about this problem. Maybe we could add > a note to the docstring of highlight-regexp saying that multi-line > regular expressions are problematic? Can someone help me find a workaround, then? If not, I would have to give up maintaining po-mode as part of GNU gettext. Said function is central in Emacs po-mode (everything else relies on it), and if multi-line regular expressions don't work, I don't know how this function could be rewritten. Bruno From unknown Fri Jun 20 19:54:56 2025 X-Loop: don@donarmstrong.com Subject: bug#192: regexp does not work as documented Reply-To: martin rudalics , 192@debbugs.gnu.org Resent-From: martin rudalics Resent-To: bug-submit-list@lists.donarmstrong.com Resent-CC: Emacs Bugs Resent-Date: Tue, 06 May 2008 12:20:04 +0000 Resent-Message-ID: Resent-Sender: don@donarmstrong.com X-Emacs-PR-Message: report 192 X-Emacs-PR-Package: emacs X-Emacs-PR-Keywords: Received: via spool by 192-submit@emacsbugs.donarmstrong.com id=B192.12100760545485 (code B ref 192); Tue, 06 May 2008 12:20:04 +0000 X-Spam-Checker-Version: SpamAssassin 3.2.3-bugs.debian.org_2005_01_02 (2007-08-08) on rzlab.ucr.edu X-Spam-Level: X-Spam-Status: No, score=0.4 required=4.0 tests=AWL,FOURLA autolearn=no version=3.2.3-bugs.debian.org_2005_01_02 Received: (at 192) by emacsbugs.donarmstrong.com; 6 May 2008 12:14:14 +0000 Received: from mail.gmx.net (mail.gmx.net [213.165.64.20]) by rzlab.ucr.edu (8.13.8/8.13.8/Debian-3) with SMTP id m46CE9Q1005478 for <192@emacsbugs.donarmstrong.com>; Tue, 6 May 2008 05:14:11 -0700 Received: (qmail invoked by alias); 06 May 2008 12:14:03 -0000 Received: from 62-47-32-217.adsl.highway.telekom.at (EHLO [62.47.32.217]) [62.47.32.217] by mail.gmx.net (mp002) with SMTP; 06 May 2008 14:14:03 +0200 X-Authenticated: #14592706 X-Provags-ID: V01U2FsdGVkX18yCGpUJqUywHXxTMpxBrZUdNdOsjT/PbSQ0STmlB 02EWWJ2vUsvJrO Message-ID: <48204B3D.6000500@gmx.at> Date: Tue, 06 May 2008 14:12:45 +0200 From: martin rudalics User-Agent: Mozilla Thunderbird 1.0 (Windows/20041206) X-Accept-Language: de-DE, de, en-us, en MIME-Version: 1.0 To: Bruno Haible CC: Chong Yidong , emacs-devel@gnu.org, koppel@ece.lsu.edu, 192@debbugs.gnu.org References: <87k5i8ukq8.fsf@stupidchicken.com> <200805061335.11379.bruno@clisp.org> In-Reply-To: <200805061335.11379.bruno@clisp.org> Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 7bit X-Y-GMX-Trusted: 0 > Can someone help me find a workaround, then? If not, I would have to give up > maintaining po-mode as part of GNU gettext. Said function is central in > Emacs po-mode (everything else relies on it), and if multi-line regular > expressions don't work, I don't know how this function could be rewritten. Don't worry, Stefan will find the solution. First of all you will probably have to (setq font-lock-multiline t) in the respective buffer. This will _not_ always DTRT after a buffer modification, as, for example, in AAAA CCCC BBBB where AAAA stands for some old text previously matched by your regexp, CCCC for some new text inserted (or old text removed), and BBBB for some text which, after the change, is now matched by the regexp (or not matched any more): In this case BBBB will be wrongly highlighted now. Alan uses the notorious `font-lock-extend-jit-lock-region-after-change' function to handle this, but it's not immediately clear how to apply this here. If everything else fails you will have to refontify till `window-end' (I prefer using a timer for such refontifications). From unknown Fri Jun 20 19:54:56 2025 X-Loop: don@donarmstrong.com Subject: bug#192: regexp does not work as documented Reply-To: David Koppelman , 192@debbugs.gnu.org Resent-From: David Koppelman Resent-To: bug-submit-list@lists.donarmstrong.com Resent-CC: Emacs Bugs Resent-Date: Tue, 06 May 2008 15:10:04 +0000 Resent-Message-ID: Resent-Sender: don@donarmstrong.com X-Emacs-PR-Message: report 192 X-Emacs-PR-Package: emacs X-Emacs-PR-Keywords: Received: via spool by 192-submit@emacsbugs.donarmstrong.com id=B192.121008601731191 (code B ref 192); Tue, 06 May 2008 15:10:04 +0000 X-Spam-Checker-Version: SpamAssassin 3.2.3-bugs.debian.org_2005_01_02 (2007-08-08) on rzlab.ucr.edu X-Spam-Level: * X-Spam-Status: No, score=1.3 required=4.0 tests=FOURLA,IMPRONONCABLE_1, MURPHY_WRONG_WORD2 autolearn=no version=3.2.3-bugs.debian.org_2005_01_02 Received: (at 192) by emacsbugs.donarmstrong.com; 6 May 2008 15:00:17 +0000 Received: from ecelsrv1.ece.lsu.edu (ecelsrv1.ece.lsu.edu [130.39.223.98]) by rzlab.ucr.edu (8.13.8/8.13.8/Debian-3) with ESMTP id m46F0Dev031055 for <192@emacsbugs.donarmstrong.com>; Tue, 6 May 2008 08:00:15 -0700 Received: from localhost (unknown [127.0.0.1]) by ecelsrv1.ece.lsu.edu (Postfix) with ESMTP id 607E228397; Tue, 6 May 2008 15:00:13 +0000 (UTC) X-Virus-Scanned: amavisd-new at ece.lsu.edu Received: from ecelsrv1.ece.lsu.edu ([127.0.0.1]) by localhost (ecelsrv1.ece.lsu.edu [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id 6YS7lXjwke2y; Tue, 6 May 2008 10:00:12 -0500 (CDT) Received: from nested.ece.lsu.edu (nested.ece.lsu.edu [130.39.222.143]) by ecelsrv1.ece.lsu.edu (Postfix) with ESMTP id 951EC2838E; Tue, 6 May 2008 10:00:12 -0500 (CDT) From: David Koppelman To: Chong Yidong Cc: emacs-devel@gnu.org, 192@debbugs.gnu.org, Bruno Haible References: <87k5i8ukq8.fsf@stupidchicken.com> Date: Tue, 06 May 2008 10:00:12 -0500 In-Reply-To: <87k5i8ukq8.fsf@stupidchicken.com> (Chong Yidong's message of "Tue, 06 May 2008 00:20:31 -0400") Message-ID: User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/23.0.60 (gnu/linux) MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable Later in the week I'll look into it and provide either a fix or document the limitation. Chong Yidong writes: > OTOH, I don't see what we can do about this problem. Maybe we could add > a note to the docstring of highlight-regexp saying that multi-line > regular expressions are problematic? Does anyone have a suggestion? Chong Yidong writes: >> $ emacs fr.po >> M-x highlight-regexp >> >> Regexp to highlight (enter this with Ctrl-Q Ctrl-J for each of the two >> newlines): >> >> ^msgstr\(\[[0-9]\]\)?.* >> \(".* >> \)* >> >> Highlight using face: hi-yellow >> >> Then move around in the buffer and look which lines are highlighted. >> In the first match already, only 5 out of 11 lines are highlighted. > > I believe this bug arises because highlight-regexp uses font-lock to > highlight the regular expression, and the font-lock engine is > intentionally limiting the region to search for the multi-line regular > expression. > > OTOH, I don't see what we can do about this problem. Maybe we could add > a note to the docstring of highlight-regexp saying that multi-line > regular expressions are problematic? Does anyone have a suggestion? > > > BTW, here is a simplified recipe, for those who didn't download the > attached file: > > 1. Copy the following text, between the "---...----" lines, into a > buffer > > ------------------ > # Messages fran=C3=A7ais pour GNU gettext. > # Copyright =C2=A9 2006 Free Software Foundation, Inc. > # Fran=C3=A7ois Pinard , 1996. > # > # > msgid "" > msgstr "" > "Project-Id-Version: GNU gettext-tools 0.16.2-pre5\n" > "Report-Msgid-Bugs-To: bug-gnu-gettext@gnu.org\n" > "POT-Creation-Date: 2007-11-02 03:23+0100\n" > "PO-Revision-Date: 2007-10-27 13:35+0200\n" > "Last-Translator: Christophe Combelles \n" > "Language-Team: French \n" > "MIME-Version: 1.0\n" > "Content-Type: text/plain; charset=3DUTF-8\n" > "Content-Transfer-Encoding: 8bit\n" > "Plural-Forms: nplurals=3D2; plural=3D(n > 1);\n" > ------------------ > > 2. M-: (highlight-regexp "^m.*\n\\(\".*\n\\)+") RET > > Note that the last two lines remain unhighlighted. From unknown Fri Jun 20 19:54:56 2025 X-Loop: don@donarmstrong.com Subject: bug#192: regexp does not work as documented Reply-To: Stefan Monnier , 192@debbugs.gnu.org Resent-From: Stefan Monnier Resent-To: bug-submit-list@lists.donarmstrong.com Resent-CC: Emacs Bugs Resent-Date: Tue, 06 May 2008 15:45:03 +0000 Resent-Message-ID: Resent-Sender: don@donarmstrong.com X-Emacs-PR-Message: report 192 X-Emacs-PR-Package: emacs X-Emacs-PR-Keywords: Received: via spool by 192-submit@emacsbugs.donarmstrong.com id=B192.121008812011395 (code B ref 192); Tue, 06 May 2008 15:45:03 +0000 X-Spam-Checker-Version: SpamAssassin 3.2.3-bugs.debian.org_2005_01_02 (2007-08-08) on rzlab.ucr.edu X-Spam-Level: X-Spam-Status: No, score=-0.5 required=4.0 tests=AWL autolearn=ham version=3.2.3-bugs.debian.org_2005_01_02 Received: (at 192) by emacsbugs.donarmstrong.com; 6 May 2008 15:35:20 +0000 Received: from mercure.iro.umontreal.ca (mercure.iro.umontreal.ca [132.204.24.67]) by rzlab.ucr.edu (8.13.8/8.13.8/Debian-3) with ESMTP id m46FZGQm011376 for <192@emacsbugs.donarmstrong.com>; Tue, 6 May 2008 08:35:18 -0700 Received: from hidalgo.iro.umontreal.ca (hidalgo.iro.umontreal.ca [132.204.27.50]) by mercure.iro.umontreal.ca (Postfix) with ESMTP id 374782CF324; Tue, 6 May 2008 11:35:14 -0400 (EDT) Received: from faina.iro.umontreal.ca (faina.iro.umontreal.ca [132.204.26.177]) by hidalgo.iro.umontreal.ca (Postfix) with ESMTP id 3BAE73FE0; Tue, 6 May 2008 11:35:01 -0400 (EDT) Received: by faina.iro.umontreal.ca (Postfix, from userid 20848) id 268DC41BEC; Tue, 6 May 2008 11:35:01 -0400 (EDT) From: Stefan Monnier To: Bruno Haible Cc: Chong Yidong , emacs-devel@gnu.org, koppel@ece.lsu.edu, 192@debbugs.gnu.org Message-ID: References: <87k5i8ukq8.fsf@stupidchicken.com> <200805061335.11379.bruno@clisp.org> Date: Tue, 06 May 2008 11:35:01 -0400 In-Reply-To: <200805061335.11379.bruno@clisp.org> (Bruno Haible's message of "Tue, 6 May 2008 13:35:11 +0200") User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/23.0.60 (gnu/linux) MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii X-DIRO-MailScanner-Information: Please contact the ISP for more information X-DIRO-MailScanner: Found to be clean X-DIRO-MailScanner-SpamCheck: n'est pas un polluriel, SpamAssassin (score=-2.82, requis 5, autolearn=not spam, ALL_TRUSTED -2.82) X-DIRO-MailScanner-From: monnier@iro.umontreal.ca > You are right that there is a limit, but it is set to 200000: > highlight-regexp is aliased to hi-lock-face-buffer, which asks for the > arguments and calls hi-lock-set-pattern. hi-lock-set-pattern does little > more than applying a margin of 100000 and calling re-search-forward. Actually, font-lock-fontified is most likely set to t, so hi-lock-set-pattern doesn't call re-sarch-forward at all and only calls font-lock-fontify-buffer instead. > - I originally observed the bug in po-mode (part of GNU gettext), in > a function po-find-span-of-entry which essentially only calls > re-search-backward and re-search-forward. Please try and reproduce the problem there and send us a recipe. Stefan From unknown Fri Jun 20 19:54:56 2025 X-Loop: don@donarmstrong.com Subject: bug#192: regexp does not work as documented Reply-To: Bruno Haible , 192@debbugs.gnu.org Resent-From: Bruno Haible Resent-To: bug-submit-list@lists.donarmstrong.com Resent-CC: Emacs Bugs Resent-Date: Tue, 06 May 2008 21:35:03 +0000 Resent-Message-ID: Resent-Sender: don@donarmstrong.com X-Emacs-PR-Message: report 192 X-Emacs-PR-Package: emacs X-Emacs-PR-Keywords: Received: via spool by 192-submit@emacsbugs.donarmstrong.com id=B192.12101093565143 (code B ref 192); Tue, 06 May 2008 21:35:03 +0000 X-Spam-Checker-Version: SpamAssassin 3.2.3-bugs.debian.org_2005_01_02 (2007-08-08) on rzlab.ucr.edu X-Spam-Level: X-Spam-Status: No, score=0.9 required=4.0 tests=AWL autolearn=ham version=3.2.3-bugs.debian.org_2005_01_02 Received: (at 192) by emacsbugs.donarmstrong.com; 6 May 2008 21:29:16 +0000 Received: from mo-p07-ob.rzone.de (mo-p07-ob.rzone.de [81.169.146.188]) by rzlab.ucr.edu (8.13.8/8.13.8/Debian-3) with ESMTP id m46LTAsg005137 for <192@emacsbugs.donarmstrong.com>; Tue, 6 May 2008 14:29:12 -0700 X-RZG-CLASS-ID: mo07 X-RZG-AUTH: gMysVb8JT2gB+rFDu0PuvnvUUGmhfq1rhHRG5dSek381RH36PlIq8YOI Received: from linuix.haible.de (dslb-084-058-049-074.pools.arcor-ip.net [84.58.49.74]) by post.webmailer.de (mrclete mo31) (RZmta 16.34) with ESMTP id e00c19k46Jj1i6 ; Tue, 6 May 2008 23:29:08 +0200 (MEST) (envelope-from: ) From: Bruno Haible To: Stefan Monnier Date: Tue, 6 May 2008 23:29:05 +0200 User-Agent: KMail/1.5.4 Cc: Chong Yidong , emacs-devel@gnu.org, koppel@ece.lsu.edu, 192@debbugs.gnu.org References: <87k5i8ukq8.fsf@stupidchicken.com> <200805061335.11379.bruno@clisp.org> In-Reply-To: MIME-Version: 1.0 Content-Type: text/plain; charset="iso-8859-1" Content-Transfer-Encoding: 7bit Content-Disposition: inline Message-Id: <200805062329.05484.bruno@clisp.org> Stefan Monnier wrote: > Actually, font-lock-fontified is most likely set to t, so > hi-lock-set-pattern doesn't call re-sarch-forward at all and only calls > font-lock-fontify-buffer instead. You're right: If I do a M-x evaluate-expression (setq font-lock-fontify-buffer nil) before M-x highlight-regexp the result is correct. So the problem is indeed with the font-locking. Bruno From unknown Fri Jun 20 19:54:56 2025 X-Loop: don@donarmstrong.com Subject: bug#192: regexp does not work as documented Reply-To: Bruno Haible , 192@debbugs.gnu.org Resent-From: Bruno Haible Resent-To: bug-submit-list@lists.donarmstrong.com Resent-CC: Emacs Bugs Resent-Date: Tue, 06 May 2008 21:45:03 +0000 Resent-Message-ID: Resent-Sender: don@donarmstrong.com X-Emacs-PR-Message: report 192 X-Emacs-PR-Package: emacs X-Emacs-PR-Keywords: Received: via spool by 192-submit@emacsbugs.donarmstrong.com id=B192.12101097708128 (code B ref 192); Tue, 06 May 2008 21:45:03 +0000 X-Spam-Checker-Version: SpamAssassin 3.2.3-bugs.debian.org_2005_01_02 (2007-08-08) on rzlab.ucr.edu X-Spam-Level: X-Spam-Status: No, score=0.7 required=4.0 tests=AWL,FOURLA autolearn=no version=3.2.3-bugs.debian.org_2005_01_02 Received: (at 192) by emacsbugs.donarmstrong.com; 6 May 2008 21:36:10 +0000 Received: from mo-p07-ob.rzone.de (mo-p07-ob.rzone.de [81.169.146.190]) by rzlab.ucr.edu (8.13.8/8.13.8/Debian-3) with ESMTP id m46La3Nk008122 for <192@emacsbugs.donarmstrong.com>; Tue, 6 May 2008 14:36:05 -0700 X-RZG-CLASS-ID: mo07 X-RZG-AUTH: gMysVb8JT2gB+rFDu0PuvnvUUGmhfq1rhHRG5dSek381RH36PlIq8YOI Received: from linuix.haible.de (dslb-084-058-049-074.pools.arcor-ip.net [84.58.49.74]) by post.webmailer.de (mrclete mo25) (RZmta 16.34) with ESMTP id 200896k46K3sKd ; Tue, 6 May 2008 23:36:02 +0200 (MEST) (envelope-from: ) From: Bruno Haible To: David Koppelman , Chong Yidong Date: Tue, 6 May 2008 23:35:59 +0200 User-Agent: KMail/1.5.4 Cc: emacs-devel@gnu.org, 192@debbugs.gnu.org References: <87k5i8ukq8.fsf@stupidchicken.com> In-Reply-To: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit Content-Disposition: inline Message-Id: <200805062335.59206.bruno@clisp.org> David Koppelman wrote: > Later in the week I'll look into it and provide either a fix > or document the limitation. Thank you! Chong Yidong wrote: > > OTOH, I don't see what we can do about this problem. Maybe we could add > > a note to the docstring of highlight-regexp saying that multi-line > > regular expressions are problematic? Does anyone have a suggestion? As an end user, for testing the effect of a regexp on a buffer interactively, I would prefer to have a "volatile" coloring (i.e. one that disappears at the next buffer modification) but is correct, rather than a documented-to-be-wrong coloring that updates itself correctly during buffer modifications. Less functionality but implemented correctly. OTOH, third-party packages may prefer the current behaviour if their regexps match only portions of a line. Bruno From unknown Fri Jun 20 19:54:56 2025 X-Loop: don@donarmstrong.com Subject: bug#192: regexp does not work as documented Reply-To: Stefan Monnier , 192@debbugs.gnu.org Resent-From: Stefan Monnier Resent-To: bug-submit-list@lists.donarmstrong.com Resent-CC: Emacs Bugs Resent-Date: Wed, 07 May 2008 01:10:05 +0000 Resent-Message-ID: Resent-Sender: don@donarmstrong.com X-Emacs-PR-Message: report 192 X-Emacs-PR-Package: emacs X-Emacs-PR-Keywords: Received: via spool by 192-submit@emacsbugs.donarmstrong.com id=B192.121012228315837 (code B ref 192); Wed, 07 May 2008 01:10:05 +0000 X-Spam-Checker-Version: SpamAssassin 3.2.3-bugs.debian.org_2005_01_02 (2007-08-08) on rzlab.ucr.edu X-Spam-Level: X-Spam-Status: No, score=0.3 required=4.0 tests=AWL autolearn=ham version=3.2.3-bugs.debian.org_2005_01_02 Received: (at 192) by emacsbugs.donarmstrong.com; 7 May 2008 01:04:43 +0000 Received: from ironport2-out.teksavvy.com (ironport2-out.pppoe.ca [206.248.154.182]) by rzlab.ucr.edu (8.13.8/8.13.8/Debian-3) with ESMTP id m4714bMg015831 for <192@emacsbugs.donarmstrong.com>; Tue, 6 May 2008 18:04:39 -0700 X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: AgoFAJudIEhMCqqd/2dsb2JhbACBU6tP X-IronPort-AV: E=Sophos;i="4.27,445,1204520400"; d="scan'208";a="20001743" Received: from smtp.pppoe.ca (HELO smtp.teksavvy.com) ([65.39.196.238]) by ironport2-out.teksavvy.com with ESMTP; 06 May 2008 21:04:19 -0400 Received: from pastel.home ([76.10.170.157]) by smtp.teksavvy.com (Internet Mail Server v1.0) with ESMTP id NGL75019; Tue, 06 May 2008 21:04:19 -0400 Received: by pastel.home (Postfix, from userid 20848) id 688597FFC; Tue, 6 May 2008 21:04:19 -0400 (EDT) From: Stefan Monnier To: Bruno Haible Cc: David Koppelman , Chong Yidong , 192@debbugs.gnu.org, emacs-devel@gnu.org Message-ID: References: <87k5i8ukq8.fsf@stupidchicken.com> <200805062335.59206.bruno@clisp.org> Date: Tue, 06 May 2008 21:04:19 -0400 In-Reply-To: <200805062335.59206.bruno@clisp.org> (Bruno Haible's message of "Tue, 6 May 2008 23:35:59 +0200") User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/23.0.60 (gnu/linux) MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii > As an end user, for testing the effect of a regexp on a buffer interactively, > I would prefer to have a "volatile" coloring (i.e. one that disappears at the > next buffer modification) but is correct, rather than a documented-to-be-wrong > coloring that updates itself correctly during buffer modifications. Less > functionality but implemented correctly. Actually, we can get the combination of the two. hilight-changes (c|sh)ould use its own loop with re-search-forward, even when font-lock is enabled. This way the highlighting would be initially correct, and in some cases it would also be correctly preserved/discovered later on. This would only be used for regexp that can span multiple lines, so highlight-changes (c|sh)ould analyse the regexp to see if there's a possibility for it to match multiple lines. Stefan From unknown Fri Jun 20 19:54:56 2025 X-Loop: don@donarmstrong.com Subject: bug#192: regexp does not work as documented Reply-To: David Koppelman , 192@debbugs.gnu.org Resent-From: David Koppelman Resent-To: bug-submit-list@lists.donarmstrong.com Resent-CC: Emacs Bugs Resent-Date: Sat, 10 May 2008 19:25:03 +0000 Resent-Message-ID: Resent-Sender: don@donarmstrong.com X-Emacs-PR-Message: report 192 X-Emacs-PR-Package: emacs X-Emacs-PR-Keywords: Received: via spool by 192-submit@emacsbugs.donarmstrong.com id=B192.121044714423748 (code B ref 192); Sat, 10 May 2008 19:25:03 +0000 X-Spam-Checker-Version: SpamAssassin 3.2.3-bugs.debian.org_2005_01_02 (2007-08-08) on rzlab.ucr.edu X-Spam-Level: * X-Spam-Status: No, score=1.3 required=4.0 tests=FOURLA,IMPRONONCABLE_1, MURPHY_WRONG_WORD2 autolearn=no version=3.2.3-bugs.debian.org_2005_01_02 Received: (at 192) by emacsbugs.donarmstrong.com; 10 May 2008 19:19:04 +0000 Received: from ecelsrv1.ece.lsu.edu (ecelsrv1.ece.lsu.edu [130.39.223.98]) by rzlab.ucr.edu (8.13.8/8.13.8/Debian-3) with ESMTP id m4AJJ0xp023742 for <192@emacsbugs.donarmstrong.com>; Sat, 10 May 2008 12:19:02 -0700 Received: from localhost (unknown [127.0.0.1]) by ecelsrv1.ece.lsu.edu (Postfix) with ESMTP id 676AF2839E; Sat, 10 May 2008 19:19:00 +0000 (UTC) X-Virus-Scanned: amavisd-new at ece.lsu.edu Received: from ecelsrv1.ece.lsu.edu ([127.0.0.1]) by localhost (ecelsrv1.ece.lsu.edu [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id D1Vpz2MRw8ec; Sat, 10 May 2008 14:18:59 -0500 (CDT) Received: from nested.ece.lsu.edu (nested.ece.lsu.edu [130.39.222.143]) by ecelsrv1.ece.lsu.edu (Postfix) with ESMTP id B248A28336; Sat, 10 May 2008 14:18:59 -0500 (CDT) From: David Koppelman To: martin rudalics Cc: Bruno Haible , Chong Yidong , 192@debbugs.gnu.org, emacs-devel@gnu.org References: <87k5i8ukq8.fsf@stupidchicken.com> <200805061335.11379.bruno@clisp.org> <48204B3D.6000500@gmx.at> Date: Sat, 10 May 2008 14:18:59 -0500 In-Reply-To: <48204B3D.6000500@gmx.at> (martin rudalics's message of "Tue, 06 May 2008 14:12:45 +0200") Message-ID: User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/23.0.60 (gnu/linux) MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii I was able to reproduce the problem with Bruno Haible's testcase and font-lock-multiline t does "fix" it. However martin rudalics warns that font-lock-multiline won't work for all cases and provides an example idea (below). I can't get that to fail. That is, with font-lock-multiline t the text was correctly fontified (though after a pause). My realization of the example was to remove and then add the first quotation mark from one of the interior lines below (also tried with more quoted lines): msgstr "" "Project-Id-Version: GNU gettext-tools 0.16.2-pre5\n" "Report-Msgid-Bugs-To: bug-gnu-gettext@gnu.org\n" "POT-Creation-Date: 2007-11-02 03:23+0100\n" "PO-Revision-Date: 2007-10-27 13:35+0200\n" "Last-Translator: Christophe Combelles \n" "Last-Translator: Christophe Combelles \n" x The fix I'm contemplating would be to warn the user when a multi-line regexp was added interactively and font-lock-multiline was nil, and then perhaps to offer to set font-lock-multiline to t (or to not set it, or to stop asking). martin rudalics writes: >> Can someone help me find a workaround, then? If not, I would have to give up >> maintaining po-mode as part of GNU gettext. Said function is central in >> Emacs po-mode (everything else relies on it), and if multi-line regular >> expressions don't work, I don't know how this function could be rewritten. > > Don't worry, Stefan will find the solution. First of all you will > probably have to > > (setq font-lock-multiline t) > > in the respective buffer. This will _not_ always DTRT after a buffer > modification, as, for example, in > > AAAA > > CCCC > > BBBB > > where AAAA stands for some old text previously matched by your regexp, > CCCC for some new text inserted (or old text removed), and BBBB for some > text which, after the change, is now matched by the regexp (or not > matched any more): In this case BBBB will be wrongly highlighted now. > Alan uses the notorious > > `font-lock-extend-jit-lock-region-after-change' > > function to handle this, but it's not immediately clear how to apply > this here. If everything else fails you will have to refontify till > `window-end' (I prefer using a timer for such refontifications). From unknown Fri Jun 20 19:54:56 2025 X-Loop: don@donarmstrong.com Subject: bug#192: regexp does not work as documented Reply-To: Bruno Haible , 192@debbugs.gnu.org Resent-From: Bruno Haible Resent-To: bug-submit-list@lists.donarmstrong.com Resent-CC: Emacs Bugs Resent-Date: Sat, 10 May 2008 20:15:03 +0000 Resent-Message-ID: Resent-Sender: don@donarmstrong.com X-Emacs-PR-Message: report 192 X-Emacs-PR-Package: emacs X-Emacs-PR-Keywords: Received: via spool by 192-submit@emacsbugs.donarmstrong.com id=B192.121044991230111 (code B ref 192); Sat, 10 May 2008 20:15:03 +0000 X-Spam-Checker-Version: SpamAssassin 3.2.3-bugs.debian.org_2005_01_02 (2007-08-08) on rzlab.ucr.edu X-Spam-Level: X-Spam-Status: No, score=0.5 required=4.0 tests=AWL,HS_INDEX_PARAM autolearn=ham version=3.2.3-bugs.debian.org_2005_01_02 Received: (at 192) by emacsbugs.donarmstrong.com; 10 May 2008 20:05:12 +0000 Received: from mo-p07-ob.rzone.de (mo-p07-ob.rzone.de [81.169.146.190]) by rzlab.ucr.edu (8.13.8/8.13.8/Debian-3) with ESMTP id m4AK51wB029219 for <192@emacsbugs.donarmstrong.com>; Sat, 10 May 2008 13:05:03 -0700 X-RZG-CLASS-ID: mo07 X-RZG-AUTH: gMysVb8JT2gB+rFDu0PuvnvUUGmhfq1rhHRG5dSek381RH36MmDLfffX7Q== Received: from linuix.haible.de (dslb-084-058-084-213.pools.arcor-ip.net [84.58.84.213]) by post.webmailer.de (klopstock mo57) (RZmta 16.34) with ESMTP id w04302k4AHYv6T ; Sat, 10 May 2008 22:04:59 +0200 (MEST) (envelope-from: ) From: Bruno Haible To: Stefan Monnier Date: Sat, 10 May 2008 22:04:56 +0200 User-Agent: KMail/1.5.4 Cc: Chong Yidong , emacs-devel@gnu.org, koppel@ece.lsu.edu, 192@debbugs.gnu.org References: <87k5i8ukq8.fsf@stupidchicken.com> <200805061335.11379.bruno@clisp.org> In-Reply-To: MIME-Version: 1.0 Content-Type: text/plain; charset="iso-8859-1" Content-Transfer-Encoding: 7bit Content-Disposition: inline Message-Id: <200805102204.56980.bruno@clisp.org> Stefan Monnier wrote: > > - I originally observed the bug in po-mode (part of GNU gettext), in > > a function po-find-span-of-entry which essentially only calls > > re-search-backward and re-search-forward. > > Please try and reproduce the problem there and send us a recipe. After deeper investigation, the bug in po-mode was not directly related: I had used a regexp which was not designed for use with re-search-backward. This bug is closed now. Thank you Stefan for bringing me on the right track. Bruno From unknown Fri Jun 20 19:54:56 2025 X-Loop: don@donarmstrong.com Subject: bug#192: regexp does not work as documented Reply-To: David Koppelman , 192@debbugs.gnu.org Resent-From: David Koppelman Resent-To: bug-submit-list@lists.donarmstrong.com Resent-CC: Emacs Bugs Resent-Date: Sat, 10 May 2008 20:20:02 +0000 Resent-Message-ID: Resent-Sender: don@donarmstrong.com X-Emacs-PR-Message: report 192 X-Emacs-PR-Package: emacs X-Emacs-PR-Keywords: Received: via spool by 192-submit@emacsbugs.donarmstrong.com id=B192.121045042131181 (code B ref 192); Sat, 10 May 2008 20:20:02 +0000 X-Spam-Checker-Version: SpamAssassin 3.2.3-bugs.debian.org_2005_01_02 (2007-08-08) on rzlab.ucr.edu X-Spam-Level: * X-Spam-Status: No, score=1.2 required=4.0 tests=AWL,IMPRONONCABLE_1, MURPHY_WRONG_WORD2 autolearn=no version=3.2.3-bugs.debian.org_2005_01_02 Received: (at 192) by emacsbugs.donarmstrong.com; 10 May 2008 20:13:41 +0000 Received: from ecelsrv1.ece.lsu.edu (ecelsrv1.ece.lsu.edu [130.39.223.98]) by rzlab.ucr.edu (8.13.8/8.13.8/Debian-3) with ESMTP id m4AKDbNZ031175 for <192@emacsbugs.donarmstrong.com>; Sat, 10 May 2008 13:13:39 -0700 Received: from localhost (unknown [127.0.0.1]) by ecelsrv1.ece.lsu.edu (Postfix) with ESMTP id B7D0E2839E; Sat, 10 May 2008 20:13:37 +0000 (UTC) X-Virus-Scanned: amavisd-new at ece.lsu.edu Received: from ecelsrv1.ece.lsu.edu ([127.0.0.1]) by localhost (ecelsrv1.ece.lsu.edu [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id fh7l+otWzISs; Sat, 10 May 2008 15:13:37 -0500 (CDT) Received: from nested.ece.lsu.edu (nested.ece.lsu.edu [130.39.222.143]) by ecelsrv1.ece.lsu.edu (Postfix) with ESMTP id 186F728018; Sat, 10 May 2008 15:13:37 -0500 (CDT) From: David Koppelman To: martin rudalics Cc: Chong Yidong , 192@debbugs.gnu.org, Bruno Haible , emacs-devel@gnu.org References: <87k5i8ukq8.fsf@stupidchicken.com> <200805061335.11379.bruno@clisp.org> <48204B3D.6000500@gmx.at> Date: Sat, 10 May 2008 15:13:37 -0500 In-Reply-To: (David Koppelman's message of "Sat, 10 May 2008 14:18:59 -0500") Message-ID: User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/23.0.60 (gnu/linux) MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii I *am* able to reproduce the font-lock-multiline limitation martin described if the buffer is in text mode. I had tried to reproduce it in emacs-lisp mode. First I'll work on the hi-lock warning as I described below, then I'll see about detecting and doing something helpful for additional situations where multi-line won't work. David Koppelman writes: > I was able to reproduce the problem with Bruno Haible's testcase and > font-lock-multiline t does "fix" it. However martin rudalics warns that > font-lock-multiline won't work for all cases and provides an example > idea (below). I can't get that to fail. That is, with > font-lock-multiline t the text was correctly fontified (though after a > pause). My realization of the example was to remove and then add the > first quotation mark from one of the interior lines below (also > tried with more quoted lines): > > msgstr "" > "Project-Id-Version: GNU gettext-tools 0.16.2-pre5\n" > "Report-Msgid-Bugs-To: bug-gnu-gettext@gnu.org\n" > "POT-Creation-Date: 2007-11-02 03:23+0100\n" > "PO-Revision-Date: 2007-10-27 13:35+0200\n" > "Last-Translator: Christophe Combelles \n" > "Last-Translator: Christophe Combelles \n" > x > > The fix I'm contemplating would be to warn the user when a multi-line > regexp was added interactively and font-lock-multiline was nil, and then > perhaps to offer to set font-lock-multiline to t (or to not set it, or > to stop asking). From unknown Fri Jun 20 19:54:56 2025 X-Loop: don@donarmstrong.com Subject: bug#192: regexp does not work as documented Reply-To: martin rudalics , 192@debbugs.gnu.org Resent-From: martin rudalics Resent-To: bug-submit-list@lists.donarmstrong.com Resent-CC: Emacs Bugs Resent-Date: Sun, 11 May 2008 08:00:04 +0000 Resent-Message-ID: Resent-Sender: don@donarmstrong.com X-Emacs-PR-Message: report 192 X-Emacs-PR-Package: emacs X-Emacs-PR-Keywords: Received: via spool by 192-submit@emacsbugs.donarmstrong.com id=B192.121049230729175 (code B ref 192); Sun, 11 May 2008 08:00:04 +0000 X-Spam-Checker-Version: SpamAssassin 3.2.3-bugs.debian.org_2005_01_02 (2007-08-08) on rzlab.ucr.edu X-Spam-Level: X-Spam-Status: No, score=-0.3 required=4.0 tests=AWL autolearn=ham version=3.2.3-bugs.debian.org_2005_01_02 Received: (at 192) by emacsbugs.donarmstrong.com; 11 May 2008 07:51:47 +0000 Received: from mail.gmx.net (mail.gmx.net [213.165.64.20]) by rzlab.ucr.edu (8.13.8/8.13.8/Debian-3) with SMTP id m4B7phk5029151 for <192@emacsbugs.donarmstrong.com>; Sun, 11 May 2008 00:51:44 -0700 Received: (qmail invoked by alias); 11 May 2008 07:51:37 -0000 Received: from 62-47-54-236.adsl.highway.telekom.at (EHLO [62.47.54.236]) [62.47.54.236] by mail.gmx.net (mp009) with SMTP; 11 May 2008 09:51:37 +0200 X-Authenticated: #14592706 X-Provags-ID: V01U2FsdGVkX1/M86d9vM3MXw7/M9IHRmbR1f3AF9VIIiYJzNfGw9 uwHW00ggCpiGAW Message-ID: <4826A303.3030002@gmx.at> Date: Sun, 11 May 2008 09:40:51 +0200 From: martin rudalics User-Agent: Mozilla Thunderbird 1.0 (Windows/20041206) X-Accept-Language: de-DE, de, en-us, en MIME-Version: 1.0 To: David Koppelman CC: Chong Yidong , 192@debbugs.gnu.org, Bruno Haible , emacs-devel@gnu.org References: <87k5i8ukq8.fsf@stupidchicken.com> <200805061335.11379.bruno@clisp.org> <48204B3D.6000500@gmx.at> In-Reply-To: Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit X-Y-GMX-Trusted: 0 > First I'll work on the hi-lock warning as I described below, then I'll > see about detecting and doing something helpful for additional > situations where multi-line won't work. Think of the following pathological case: Devise a regexp to highlight the first line of a buffer provided the buffer does not end with a newline. Doing this with `font-lock-multiline' hardly makes any sense. Maybe users should classify whether a regexp they use (1) doesn't match newlines - no `font-lock-multiline' needed, (2) match at most n newlines in which case you should tell font-lock to rescan from n lines before each buffer change (with large n the display engine will suffer noticeably, mainly because font-lock has to search for all other keywords as well), or (3) may match more than n newlines in which case you should use an idle timer to scan the entire buffer for any matches of such regexps and highlight them separately. From unknown Fri Jun 20 19:54:56 2025 X-Loop: don@donarmstrong.com Subject: bug#192: regexp does not work as documented Reply-To: Chong Yidong , 192@debbugs.gnu.org Resent-From: Chong Yidong Resent-To: bug-submit-list@lists.donarmstrong.com Resent-CC: Emacs Bugs Resent-Date: Sun, 11 May 2008 14:35:03 +0000 Resent-Message-ID: Resent-Sender: don@donarmstrong.com X-Emacs-PR-Message: report 192 X-Emacs-PR-Package: emacs X-Emacs-PR-Keywords: Received: via spool by 192-submit@emacsbugs.donarmstrong.com id=B192.121051607918945 (code B ref 192); Sun, 11 May 2008 14:35:03 +0000 X-Spam-Checker-Version: SpamAssassin 3.2.3-bugs.debian.org_2005_01_02 (2007-08-08) on rzlab.ucr.edu X-Spam-Level: ** X-Spam-Status: No, score=2.5 required=4.0 tests=AWL,FOURLA,RCVD_IN_PBL, RCVD_IN_SORBS_DUL,RDNS_DYNAMIC autolearn=no version=3.2.3-bugs.debian.org_2005_01_02 Received: (at 192) by emacsbugs.donarmstrong.com; 11 May 2008 14:27:59 +0000 Received: from furry (c-98-216-111-182.hsd1.ma.comcast.net [98.216.111.182]) by rzlab.ucr.edu (8.13.8/8.13.8/Debian-3) with ESMTP id m4BERuAW018939 for <192@emacsbugs.donarmstrong.com>; Sun, 11 May 2008 07:27:57 -0700 Received: by furry (Postfix, from userid 1000) id AF917C049; Sun, 11 May 2008 10:27:50 -0400 (EDT) From: Chong Yidong To: martin rudalics Cc: David Koppelman , 192@debbugs.gnu.org, Bruno Haible , emacs-devel@gnu.org References: <87k5i8ukq8.fsf@stupidchicken.com> <200805061335.11379.bruno@clisp.org> <48204B3D.6000500@gmx.at> <4826A303.3030002@gmx.at> Date: Sun, 11 May 2008 10:27:50 -0400 In-Reply-To: <4826A303.3030002@gmx.at> (martin rudalics's message of "Sun, 11 May 2008 09:40:51 +0200") Message-ID: <87abiwoqzd.fsf@stupidchicken.com> User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/23.0.60 (gnu/linux) MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii martin rudalics writes: >> First I'll work on the hi-lock warning as I described below, then I'll >> see about detecting and doing something helpful for additional >> situations where multi-line won't work. > > Think of the following pathological case: Devise a regexp to highlight > the first line of a buffer provided the buffer does not end with a > newline. Doing this with `font-lock-multiline' hardly makes any sense. Ideally, highlight-regexp should work automagically, instead of forcing users to do something extra to make their multi-line regexp work properly. The right way to do this is probably for hi-lock-mode to process the buffer initially, setting up text properties to make font-lock DTRT even for multi-line expressions. But that's a big job. As for making hi-lock-mode detect whether or not a regexp is multi-line, isn't that a computationally non-trivial problem? Maybe making hi-lock-mode turn on font-lock-multiline, while not foolproof, works often enough to be satisfactory. From unknown Fri Jun 20 19:54:56 2025 X-Loop: don@donarmstrong.com Subject: bug#192: regexp does not work as documented Reply-To: David Koppelman , 192@debbugs.gnu.org Resent-From: David Koppelman Resent-To: bug-submit-list@lists.donarmstrong.com Resent-CC: Emacs Bugs Resent-Date: Sun, 11 May 2008 15:45:02 +0000 Resent-Message-ID: Resent-Sender: don@donarmstrong.com X-Emacs-PR-Message: report 192 X-Emacs-PR-Package: emacs X-Emacs-PR-Keywords: Received: via spool by 192-submit@emacsbugs.donarmstrong.com id=B192.121052021428413 (code B ref 192); Sun, 11 May 2008 15:45:02 +0000 X-Spam-Checker-Version: SpamAssassin 3.2.3-bugs.debian.org_2005_01_02 (2007-08-08) on rzlab.ucr.edu X-Spam-Level: X-Spam-Status: No, score=0.7 required=4.0 tests=AWL,FOURLA autolearn=no version=3.2.3-bugs.debian.org_2005_01_02 Received: (at 192) by emacsbugs.donarmstrong.com; 11 May 2008 15:36:54 +0000 Received: from ecelsrv1.ece.lsu.edu (ecelsrv1.ece.lsu.edu [130.39.223.98]) by rzlab.ucr.edu (8.13.8/8.13.8/Debian-3) with ESMTP id m4BFao0n028407 for <192@emacsbugs.donarmstrong.com>; Sun, 11 May 2008 08:36:51 -0700 Received: from localhost (unknown [127.0.0.1]) by ecelsrv1.ece.lsu.edu (Postfix) with ESMTP id 6B1DB2833D; Sun, 11 May 2008 15:36:50 +0000 (UTC) X-Virus-Scanned: amavisd-new at ece.lsu.edu Received: from ecelsrv1.ece.lsu.edu ([127.0.0.1]) by localhost (ecelsrv1.ece.lsu.edu [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id wJjrDJ2jbWh7; Sun, 11 May 2008 10:36:49 -0500 (CDT) Received: from nested.ece.lsu.edu (nested.ece.lsu.edu [130.39.222.143]) by ecelsrv1.ece.lsu.edu (Postfix) with ESMTP id BDC2428316; Sun, 11 May 2008 10:36:49 -0500 (CDT) From: David Koppelman To: Chong Yidong Cc: martin rudalics , 192@debbugs.gnu.org, Bruno Haible , emacs-devel@gnu.org References: <87k5i8ukq8.fsf@stupidchicken.com> <200805061335.11379.bruno@clisp.org> <48204B3D.6000500@gmx.at> <4826A303.3030002@gmx.at> <87abiwoqzd.fsf@stupidchicken.com> Date: Sun, 11 May 2008 10:36:49 -0500 In-Reply-To: <87abiwoqzd.fsf@stupidchicken.com> (Chong Yidong's message of "Sun, 11 May 2008 10:27:50 -0400") Message-ID: User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/23.0.60 (gnu/linux) MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii I agree pretty much with everything Chong Yidong writes. I rather not bother the user with an additional question if I don't have to, the alternative would be a warning. My latest plan is to do what Chong Yidong suggests, setting up text properties so that font-lock DTRT, though it doesn't seem as hard as he suggests (I'm still in the naive enthusiasm stage). I tried adding the font-lock-multiline property to the face property list passed to font lock and that did the trick, even with the font-lock-multiline variable nil. I rather do that than turn on font-lock-multiline because I'm assuming that font-lock-multiline is set to nil in most cases for a good reason. Rather than perfectly distinguishing multi-line from single line patterns guessing would be good enough for hi-lock. I'm using the following regexp, "\\(\n.\\|\\\\W[*+]\\|\\\\[SC].[*+]\\|\\[\\^[^]]+\\][+*]\\)", which hopefully isn't too far from covering a large majority of interactively entered patterns. I actually thought about properly parsing the regexp, but the effort to do that could be spent on making multi-line patterns work properly, at least if they don't span too many lines. One more thing, multi-line regexp matches don't work properly even with font-lock-multiline t when jit-lock is being used in a buffer without syntactic fontification and using the default setting of jit-lock-contextually, setting it to t gets multi-line fontification to work. I plan to play around a bit more and come up with something, maybe today, maybe early this week. Chong Yidong writes: > Ideally, highlight-regexp should work automagically, instead of forcing > users to do something extra to make their multi-line regexp work > properly. The right way to do this is probably for hi-lock-mode to > process the buffer initially, setting up text properties to make > font-lock DTRT even for multi-line expressions. But that's a big job. > > As for making hi-lock-mode detect whether or not a regexp is multi-line, > isn't that a computationally non-trivial problem? > > Maybe making hi-lock-mode turn on font-lock-multiline, while not > foolproof, works often enough to be satisfactory. From unknown Fri Jun 20 19:54:56 2025 X-Loop: don@donarmstrong.com Subject: bug#192: regexp does not work as documented Reply-To: Stefan Monnier , 192@debbugs.gnu.org Resent-From: Stefan Monnier Resent-To: bug-submit-list@lists.donarmstrong.com Resent-CC: Emacs Bugs Resent-Date: Sun, 11 May 2008 18:50:03 +0000 Resent-Message-ID: Resent-Sender: don@donarmstrong.com X-Emacs-PR-Message: report 192 X-Emacs-PR-Package: emacs X-Emacs-PR-Keywords: Received: via spool by 192-submit@emacsbugs.donarmstrong.com id=B192.121053146220865 (code B ref 192); Sun, 11 May 2008 18:50:03 +0000 X-Spam-Checker-Version: SpamAssassin 3.2.3-bugs.debian.org_2005_01_02 (2007-08-08) on rzlab.ucr.edu X-Spam-Level: X-Spam-Status: No, score=0.5 required=4.0 tests=AWL,FOURLA autolearn=no version=3.2.3-bugs.debian.org_2005_01_02 Received: (at 192) by emacsbugs.donarmstrong.com; 11 May 2008 18:44:22 +0000 Received: from ironport2-out.teksavvy.com (ironport2-out.pppoe.ca [206.248.154.182]) by rzlab.ucr.edu (8.13.8/8.13.8/Debian-3) with ESMTP id m4BIiINA020859 for <192@emacsbugs.donarmstrong.com>; Sun, 11 May 2008 11:44:20 -0700 X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: AmoCABPbJkjO+JgrdGdsb2JhbACBU5A5ASeXBA X-IronPort-AV: E=Sophos;i="4.27,469,1204520400"; d="scan'208";a="20288304" Received: from smtp.pppoe.ca (HELO smtp.teksavvy.com) ([65.39.196.238]) by ironport2-out.teksavvy.com with ESMTP; 11 May 2008 14:44:12 -0400 Received: from pastel.home ([206.248.152.43]) by smtp.teksavvy.com (Internet Mail Server v1.0) with ESMTP id RXD65612; Sun, 11 May 2008 14:44:12 -0400 Received: by pastel.home (Postfix, from userid 20848) id 25DDD8265; Sun, 11 May 2008 14:44:12 -0400 (EDT) From: Stefan Monnier To: David Koppelman Cc: Chong Yidong , martin rudalics , 192@debbugs.gnu.org, Bruno Haible , emacs-devel@gnu.org Message-ID: References: <87k5i8ukq8.fsf@stupidchicken.com> <200805061335.11379.bruno@clisp.org> <48204B3D.6000500@gmx.at> <4826A303.3030002@gmx.at> <87abiwoqzd.fsf@stupidchicken.com> Date: Sun, 11 May 2008 14:44:12 -0400 In-Reply-To: (David Koppelman's message of "Sun, 11 May 2008 10:36:49 -0500") User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/23.0.60 (gnu/linux) MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii > My latest plan is to do what Chong Yidong suggests, setting up text > properties so that font-lock DTRT, though it doesn't seem as hard as he > suggests (I'm still in the naive enthusiasm stage). Indeed, it shouldn't be that hard. > I tried adding the font-lock-multiline property to the face property > list passed to font lock and that did the trick, even with the > font-lock-multiline variable nil. That may not be enough. You'll probably want to do something like what smerge does: (while (re-search-forward nil t) (font-lock-fontify-region (match-beginning 0) (match-end 0))) this will find all the multiline elements. And the font-lock-multiline property you add will make sure that those that were found will not disappear accidentally because of some later refontification. > I rather do that than turn on font-lock-multiline because I'm assuming > that font-lock-multiline is set to nil in most cases for > a good reason. Setting the `font-lock-multiline' variable to t has a performance cost. > I actually thought about properly parsing the regexp, but the effort to > do that could be spent on making multi-line patterns work properly, at > least if they don't span too many lines. If someone wants that, I have a parser that takes a regexp and turns it into something like `rx' syntax. It uses my lex.el library (which takes an `rx'-like input syntax). > One more thing, multi-line regexp matches don't work properly even > with font-lock-multiline t when jit-lock is being used in a buffer > without syntactic fontification and using the default setting of > jit-lock-contextually, setting it to t gets multi-line fontification > to work. The `font-lock-multiline' variable only tells font-lock that if it ever bumps into a multiline element, it should mark it (with the font-lock-multiline property) so that it will not re-fontify it as a whole if it ever needs to refontify it. So it doesn't solve the problem of "how do I make sure that font-lock indeed finds the multiline element". Multiline elements can only be found when font-locking a large enough piece of text, which tends to only happen during the initial fontification, or during background or contextual refontification, or during an explicit call such as in the above while loop. Stefan From unknown Fri Jun 20 19:54:56 2025 X-Loop: don@donarmstrong.com Subject: bug#192: regexp does not work as documented Reply-To: Stefan Monnier , 192@debbugs.gnu.org Resent-From: Stefan Monnier Resent-To: bug-submit-list@lists.donarmstrong.com Resent-CC: Emacs Bugs Resent-Date: Sun, 11 May 2008 18:50:05 +0000 Resent-Message-ID: Resent-Sender: don@donarmstrong.com X-Emacs-PR-Message: report 192 X-Emacs-PR-Package: emacs X-Emacs-PR-Keywords: Received: via spool by 192-submit@emacsbugs.donarmstrong.com id=B192.121053150420912 (code B ref 192); Sun, 11 May 2008 18:50:05 +0000 X-Spam-Checker-Version: SpamAssassin 3.2.3-bugs.debian.org_2005_01_02 (2007-08-08) on rzlab.ucr.edu X-Spam-Level: X-Spam-Status: No, score=0.4 required=4.0 tests=AWL autolearn=ham version=3.2.3-bugs.debian.org_2005_01_02 Received: (at 192) by emacsbugs.donarmstrong.com; 11 May 2008 18:45:04 +0000 Received: from ironport2-out.teksavvy.com (ironport2-out.teksavvy.com [206.248.154.182]) by rzlab.ucr.edu (8.13.8/8.13.8/Debian-3) with ESMTP id m4BIj0MB020866 for <192@emacsbugs.donarmstrong.com>; Sun, 11 May 2008 11:45:02 -0700 X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: AmoCABPbJkjO+JgrdGdsb2JhbACBU5A5ASeXBA X-IronPort-AV: E=Sophos;i="4.27,469,1204520400"; d="scan'208";a="20288327" Received: from smtp.pppoe.ca (HELO smtp.teksavvy.com) ([65.39.196.238]) by ironport2-out.teksavvy.com with ESMTP; 11 May 2008 14:44:55 -0400 Received: from pastel.home ([206.248.152.43]) by smtp.teksavvy.com (Internet Mail Server v1.0) with ESMTP id RXD67155; Sun, 11 May 2008 14:44:55 -0400 Received: by pastel.home (Postfix, from userid 20848) id 32B438265; Sun, 11 May 2008 14:44:55 -0400 (EDT) From: Stefan Monnier To: Chong Yidong Cc: martin rudalics , David Koppelman , 192@debbugs.gnu.org, Bruno Haible , emacs-devel@gnu.org Message-ID: References: <87k5i8ukq8.fsf@stupidchicken.com> <200805061335.11379.bruno@clisp.org> <48204B3D.6000500@gmx.at> <4826A303.3030002@gmx.at> <87abiwoqzd.fsf@stupidchicken.com> Date: Sun, 11 May 2008 14:44:55 -0400 In-Reply-To: <87abiwoqzd.fsf@stupidchicken.com> (Chong Yidong's message of "Sun, 11 May 2008 10:27:50 -0400") User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/23.0.60 (gnu/linux) MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii > As for making hi-lock-mode detect whether or not a regexp is multi-line, > isn't that a computationally non-trivial problem? Well, you can turn the regexp into a DFA, then take the ".*\n.+" regexp, turn it into another DFA, take the intersection of the two DFAs, and if it's empty you know your regexp can never match a multiline element. Stefan From unknown Fri Jun 20 19:54:56 2025 X-Loop: don@donarmstrong.com Subject: bug#192: regexp does not work as documented Reply-To: David Koppelman , 192@debbugs.gnu.org Resent-From: David Koppelman Resent-To: bug-submit-list@lists.donarmstrong.com Resent-CC: Emacs Bugs Resent-Date: Sun, 11 May 2008 19:15:03 +0000 Resent-Message-ID: Resent-Sender: don@donarmstrong.com X-Emacs-PR-Message: report 192 X-Emacs-PR-Package: emacs X-Emacs-PR-Keywords: Received: via spool by 192-submit@emacsbugs.donarmstrong.com id=B192.121053297724704 (code B ref 192); Sun, 11 May 2008 19:15:03 +0000 X-Spam-Checker-Version: SpamAssassin 3.2.3-bugs.debian.org_2005_01_02 (2007-08-08) on rzlab.ucr.edu X-Spam-Level: X-Spam-Status: No, score=0.5 required=4.0 tests=AWL,FOURLA autolearn=no version=3.2.3-bugs.debian.org_2005_01_02 Received: (at 192) by emacsbugs.donarmstrong.com; 11 May 2008 19:09:37 +0000 Received: from ecelsrv1.ece.lsu.edu (ecelsrv1.ece.lsu.edu [130.39.223.98]) by rzlab.ucr.edu (8.13.8/8.13.8/Debian-3) with ESMTP id m4BJ9Wuu024698 for <192@emacsbugs.donarmstrong.com>; Sun, 11 May 2008 12:09:34 -0700 Received: from localhost (unknown [127.0.0.1]) by ecelsrv1.ece.lsu.edu (Postfix) with ESMTP id A955E28350; Sun, 11 May 2008 19:09:32 +0000 (UTC) X-Virus-Scanned: amavisd-new at ece.lsu.edu Received: from ecelsrv1.ece.lsu.edu ([127.0.0.1]) by localhost (ecelsrv1.ece.lsu.edu [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id fr7PlMx0JlAw; Sun, 11 May 2008 14:09:32 -0500 (CDT) Received: from nested.ece.lsu.edu (nested.ece.lsu.edu [130.39.222.143]) by ecelsrv1.ece.lsu.edu (Postfix) with ESMTP id C5F1D2833B; Sun, 11 May 2008 14:09:31 -0500 (CDT) From: David Koppelman To: Stefan Monnier Cc: Chong Yidong , martin rudalics , 192@debbugs.gnu.org, Bruno Haible , emacs-devel@gnu.org References: <87k5i8ukq8.fsf@stupidchicken.com> <200805061335.11379.bruno@clisp.org> <48204B3D.6000500@gmx.at> <4826A303.3030002@gmx.at> <87abiwoqzd.fsf@stupidchicken.com> Date: Sun, 11 May 2008 14:09:31 -0500 In-Reply-To: (Stefan Monnier's message of "Sun, 11 May 2008 14:44:12 -0400") Message-ID: User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/23.0.60 (gnu/linux) MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii I've decided against having hi-lock turn on font-lock-multiline or even apply font-lock-multiline text properties, too much potential to slow things down to a crawl when an unsuspecting user enters a regexp. If I understand things correctly, the font-lock-multiline property is used to extend a region to be fontified, a region to be used for *all* keywords. This would have disastrous effects when multi-line patterns span, say, 100's of lines for modes with hundreds of keywords. I had been toying with the idea of limiting extended regions to something like 100 lines, but that still seems wasteful when most keywords are single line (I haven't benchmarked anything yet). A better solution would be to have font-lock use multi-line extended regions selectively. Perhaps a hint in the current keyword syntax (say, explicitly applying the font-lock-multiline property), or a separate method for providing multi-line keywords to font-lock. Such keywords would get the multi-line extended regions, the other just the whole-line extensions (or whatever the hooks do). Is this something the font-lock maintainers would consider? What I'll do now is just document the limitations for hi-lock and perhaps provide a warning when a multiline pattern is used. > That may not be enough. You'll probably want to do something like what > smerge does: > > (while (re-search-forward nil t) > (font-lock-fontify-region (match-beginning 0) (match-end 0))) I wouldn't do that without suppressing other keywords. > If someone wants that, I have a parser that takes a regexp and turns it > into something like `rx' syntax. It uses my lex.el library (which > takes an `rx'-like input syntax). That sounds useful, either E-mail it to me or let me know where to find it. Stefan Monnier writes: >> My latest plan is to do what Chong Yidong suggests, setting up text >> properties so that font-lock DTRT, though it doesn't seem as hard as he >> suggests (I'm still in the naive enthusiasm stage). > > Indeed, it shouldn't be that hard. > >> I tried adding the font-lock-multiline property to the face property >> list passed to font lock and that did the trick, even with the >> font-lock-multiline variable nil. > > That may not be enough. You'll probably want to do something like what > smerge does: > > (while (re-search-forward nil t) > (font-lock-fontify-region (match-beginning 0) (match-end 0))) > > this will find all the multiline elements. And the font-lock-multiline > property you add will make sure that those that were found will not > disappear accidentally because of some later refontification. > >> I rather do that than turn on font-lock-multiline because I'm assuming >> that font-lock-multiline is set to nil in most cases for >> a good reason. > > Setting the `font-lock-multiline' variable to t has a performance cost. > >> I actually thought about properly parsing the regexp, but the effort to >> do that could be spent on making multi-line patterns work properly, at >> least if they don't span too many lines. > > If someone wants that, I have a parser that takes a regexp and turns it > into something like `rx' syntax. It uses my lex.el library (which > takes an `rx'-like input syntax). > >> One more thing, multi-line regexp matches don't work properly even >> with font-lock-multiline t when jit-lock is being used in a buffer >> without syntactic fontification and using the default setting of >> jit-lock-contextually, setting it to t gets multi-line fontification >> to work. > > The `font-lock-multiline' variable only tells font-lock that if it ever > bumps into a multiline element, it should mark it (with the > font-lock-multiline property) so that it will not re-fontify it as > a whole if it ever needs to refontify it. > > So it doesn't solve the problem of "how do I make sure that font-lock > indeed finds the multiline element". Multiline elements can only be > found when font-locking a large enough piece of text, which tends to > only happen during the initial fontification, or during background or > contextual refontification, or during an explicit call such as in the > above while loop. > > > Stefan From unknown Fri Jun 20 19:54:56 2025 X-Loop: don@donarmstrong.com Subject: bug#192: regexp does not work as documented Reply-To: Thomas Lord , 192@debbugs.gnu.org Resent-From: Thomas Lord Resent-To: bug-submit-list@lists.donarmstrong.com Resent-CC: Emacs Bugs Resent-Date: Sun, 11 May 2008 19:25:03 +0000 Resent-Message-ID: Resent-Sender: don@donarmstrong.com X-Emacs-PR-Message: report 192 X-Emacs-PR-Package: emacs X-Emacs-PR-Keywords: Received: via spool by 192-submit@emacsbugs.donarmstrong.com id=B192.121053360125971 (code B ref 192); Sun, 11 May 2008 19:25:03 +0000 X-Spam-Checker-Version: SpamAssassin 3.2.3-bugs.debian.org_2005_01_02 (2007-08-08) on rzlab.ucr.edu X-Spam-Level: * X-Spam-Status: No, score=1.6 required=4.0 tests=HTML_MESSAGE,SPF_HELO_PASS autolearn=no version=3.2.3-bugs.debian.org_2005_01_02 Received: (at 192) by emacsbugs.donarmstrong.com; 11 May 2008 19:20:01 +0000 Received: from mail.42inc.com (mail.42inc.com [205.149.0.25]) by rzlab.ucr.edu (8.13.8/8.13.8/Debian-3) with ESMTP id m4BJJtVP025946 for <192@emacsbugs.donarmstrong.com>; Sun, 11 May 2008 12:19:56 -0700 X-TFF-CGPSA-Version: 1.5 X-TFF-CGPSA-Filter-42inc: Scanned X-42-Virus-Scanned: by 42 Antivirus -- Found to be clean. Received: from [69.236.114.9] (account lord@emf.net HELO [192.168.1.64]) by mail.42inc.com (CommuniGate Pro SMTP 5.0.13) with ESMTPA id 30292298; Sun, 11 May 2008 12:19:49 -0700 Message-ID: <482750F4.2050102@emf.net> Date: Sun, 11 May 2008 13:03:00 -0700 From: Thomas Lord User-Agent: Thunderbird 1.5.0.5 (X11/20060808) MIME-Version: 1.0 To: Stefan Monnier CC: Chong Yidong , martin rudalics , David Koppelman , 192@debbugs.gnu.org, Bruno Haible , emacs-devel@gnu.org References: <87k5i8ukq8.fsf@stupidchicken.com> <200805061335.11379.bruno@clisp.org> <48204B3D.6000500@gmx.at> <4826A303.3030002@gmx.at> <87abiwoqzd.fsf@stupidchicken.com> In-Reply-To: Content-Type: multipart/alternative; boundary="------------070006010001000508030704" This is a multi-part message in MIME format. --------------070006010001000508030704 Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit >> As for making hi-lock-mode detect whether or not a regexp is multi-line, >> isn't that a computationally non-trivial problem? >> > > Well, you can turn the regexp into a DFA, then take the ".*\n.+" regexp, > turn it into another DFA, take the intersection of the two DFAs, and if > it's empty you know your regexp can never match a multiline element. > If you are going to go that that trouble, perhaps there is a better solution: The Rx pattern matcher found in distributions of GNU Arch has these relevant capabilities (relevant at least so far as I understand the problem you are trying to solve): 1. It does on-the-fly regexp->DFA conversion, degrading gracefully into mixed NFA/DFA mode or pure NFA mode if the DFA would be too large. The calling program gets to say what "too large" is. 2. Although it is a C library, you can capture what is (in essence) the continuation of an on-going match. That is, you can suspend a match (or scan) part-way through, then later resume from that point, perhaps multiple times. (This does not involve abusing the C stack.) 3. It does have some Unicode support in there and, though these capabilities are under-tested and some features are missing, it is quite flexible about encoding forms. 4. The DFA construction is "caching" and, for a given regexp, all uses will share the DFA construction. E.g., multiple, suspended regexp continuations can be space efficient because they will share state. 5. Because of the caching and structure sharing, you can tell if two continuations from a single regexp have arrived at the same state with a C EQ test ("=="). How can this help? Well, instead of using heuristics to decide where to re-scan from and too, you can cache a record of where the DFA scan arrived at for periodic positions in the buffer. Then begin scanning from just before any modification for as far as it takes to arrive at a DFA state that is the same as last time, updating any highlighting in the region between those two points. I don't mean to imply that this is a trivial thing to implement in Emacs but if you start getting up to building DFAs (very expensive in the worst case) and taking intersections (very expensive in the worst case) -- both also not all that simple to implement (nor obviously possible for Emacs' extended regexp language) -- then the effort may be comparable and (re-)visiting the option to adapt Rx to Emacs should be worth considering. As a point of amusement and credit where due, I think it was Jim Blandy who first noticed this possibility in the early 1990s when I was explaining to him the capabilities I was then just beginning to add to Rx. This is a very old problem, long recognized, with some work already done on a (purportedly) Right Thing solution. -t --------------070006010001000508030704 Content-Type: text/html; charset=ISO-8859-1 Content-Transfer-Encoding: 7bit
As for making hi-lock-mode detect whether or not a regexp is multi-line,
isn't that a computationally non-trivial problem?
    

Well, you can turn the regexp into a DFA, then take the ".*\n.+" regexp,
turn it into another DFA, take the intersection of the two DFAs, and if
it's empty you know your regexp can never match a multiline element.
  

If you are going to go that that trouble, perhaps there is a better solution:

The Rx pattern matcher found in distributions of GNU Arch has these
relevant capabilities (relevant at least so far as I understand the problem you
are trying to solve):

1. It does on-the-fly regexp->DFA conversion, degrading gracefully into
    mixed NFA/DFA mode or pure NFA mode if the DFA would be too
    large.   The calling program gets to say what "too large" is.

2. Although it is a C library, you can capture what is (in essence) the
    continuation of an on-going match.   That is, you can suspend a
    match (or scan) part-way through, then later resume from that point,
    perhaps multiple times.   (This does not involve abusing the C stack.)

3. It does have some Unicode support in there and, though these capabilities
    are under-tested and some features are missing, it is quite flexible about
    encoding forms.

4. The DFA construction is "caching" and, for a given regexp, all uses
    will share the DFA construction.   E.g., multiple, suspended regexp
    continuations can be space efficient because they will share state.

5. Because of the caching and structure sharing, you can tell if two continuations
    from a single regexp have arrived at the same state with a C EQ test ("==").

How can this help?

Well, instead of using heuristics to decide where to re-scan from and too, you
can cache a record of where the DFA scan arrived at for periodic positions in the
buffer.   Then begin scanning from just before any modification for as far as it
takes to arrive at a DFA state that is the same as last time, updating any highlighting
in the region between those two points.

I don't mean to imply that this is a trivial thing to implement in Emacs but
if you start getting up to building DFAs (very expensive in the worst case) and
taking intersections (very expensive in the worst case) -- both also not all that
simple to implement (nor obviously possible for Emacs' extended regexp language) --
then the effort may be comparable and (re-)visiting the option to adapt Rx to Emacs
should be worth considering.

As a point of amusement and credit where due, I think it was Jim Blandy who first noticed this
possibility in the early 1990s when I was explaining to him the capabilities I
was then just beginning to add to Rx.

This is a very old problem, long recognized, with some work already done on
a (purportedly) Right Thing solution.

-t


--------------070006010001000508030704-- From unknown Fri Jun 20 19:54:56 2025 X-Loop: don@donarmstrong.com Subject: bug#192: regexp does not work as documented Reply-To: Stefan Monnier , 192@debbugs.gnu.org Resent-From: Stefan Monnier Resent-To: bug-submit-list@lists.donarmstrong.com Resent-CC: Emacs Bugs Resent-Date: Mon, 12 May 2008 01:35:03 +0000 Resent-Message-ID: Resent-Sender: don@donarmstrong.com X-Emacs-PR-Message: report 192 X-Emacs-PR-Package: emacs X-Emacs-PR-Keywords: Received: via spool by 192-submit@emacsbugs.donarmstrong.com id=B192.121055571011085 (code B ref 192); Mon, 12 May 2008 01:35:03 +0000 X-Spam-Checker-Version: SpamAssassin 3.2.3-bugs.debian.org_2005_01_02 (2007-08-08) on rzlab.ucr.edu X-Spam-Level: X-Spam-Status: No, score=0.5 required=4.0 tests=AWL,FOURLA autolearn=no version=3.2.3-bugs.debian.org_2005_01_02 Received: (at 192) by emacsbugs.donarmstrong.com; 12 May 2008 01:28:30 +0000 Received: from ironport2-out.teksavvy.com (ironport2-out.pppoe.ca [206.248.154.182]) by rzlab.ucr.edu (8.13.8/8.13.8/Debian-3) with ESMTP id m4C1SPHc011079 for <192@emacsbugs.donarmstrong.com>; Sun, 11 May 2008 18:28:27 -0700 X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: AmoCAAs6J0jO+JgrdGdsb2JhbACBU5A6ASeXCw X-IronPort-AV: E=Sophos;i="4.27,470,1204520400"; d="el'?scan'208";a="20308168" Received: from smtp.pppoe.ca (HELO smtp.teksavvy.com) ([65.39.196.238]) by ironport2-out.teksavvy.com with ESMTP; 11 May 2008 21:28:19 -0400 Received: from pastel.home ([206.248.152.43]) by smtp.teksavvy.com (Internet Mail Server v1.0) with ESMTP id SGO89018; Sun, 11 May 2008 21:28:18 -0400 Received: by pastel.home (Postfix, from userid 20848) id 702CD7F83; Sun, 11 May 2008 21:28:18 -0400 (EDT) From: Stefan Monnier To: David Koppelman Cc: martin rudalics , Chong Yidong , 192@debbugs.gnu.org, Bruno Haible , emacs-devel@gnu.org Message-ID: References: <87k5i8ukq8.fsf@stupidchicken.com> <200805061335.11379.bruno@clisp.org> <48204B3D.6000500@gmx.at> <4826A303.3030002@gmx.at> <87abiwoqzd.fsf@stupidchicken.com> Date: Sun, 11 May 2008 21:28:18 -0400 In-Reply-To: (David Koppelman's message of "Sun, 11 May 2008 14:09:31 -0500") User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/23.0.60 (gnu/linux) MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="=-=-=" --=-=-= > A better solution would be to have font-lock use multi-line extended > regions selectively. Perhaps a hint in the current keyword syntax > (say, explicitly applying the font-lock-multiline property), or a > separate method for providing multi-line keywords to font-lock. I don't understand the difference between the above and the application of font-lock-multiline properties which you seem to have tried and rejected. I don't necessarily disagree with your rejection of font-lock-multiline: it can have disastrous effect indeed if the multiline region becomes large. > Such keywords would get the multi-line extended regions, the other > just the whole-line extensions (or whatever the hooks do). > Is this something the font-lock maintainers would consider? I guess I simply do not understand what you propose. Any improvement in the multiline handling is welcome, but beware: this is not an easy area. >> (while (re-search-forward nil t) >> (font-lock-fontify-region (match-beginning 0) (match-end 0))) > I wouldn't do that without suppressing other keywords. FWIW, I do pretty much exactly the above loop in smerge-mode and I haven't heard complaints yet. >> If someone wants that, I have a parser that takes a regexp and turns it >> into something like `rx' syntax. It uses my lex.el library (which >> takes an `rx'-like input syntax). > That sounds useful, either E-mail it to me or let me know > where to find it. Find the current version attached. Consider it as 99.9% untested code, tho. Also you need to eval it before you can byte-compile it. And I strongly recommend you byte-compile it to reduce the specpdl usage. Stefan --=-=-= Content-Type: application/emacs-lisp Content-Disposition: attachment; filename=lex.el Content-Transfer-Encoding: quoted-printable ;;; lex.el --- Lexical analyser construction ;; Copyright (C) 2008 Stefan Monnier ;; Author: Stefan Monnier ;; Keywords:=20 ;; This program is free software; you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by ;; the Free Software Foundation, either version 3 of the License, or ;; (at your option) any later version. ;; This program is distributed in the hope that it will be useful, ;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;; GNU General Public License for more details. ;; You should have received a copy of the GNU General Public License ;; along with this program. If not, see . ;;; Commentary: ;; Format or regexps, is the same as used for `rx' and `sregex'. ;; Additions: ;; - (ere RE) specify regexps using the ERE syntax. ;; - (inter REs...) (aka `&') make a regexp that only matches ;; if all its branches match. E.g. (inter (ere ".*a.*") (ere ".*b.*")) ;; match any string that contain both an "a" and a "b", in any order. ;; - (case-fold REs...) and (case-sensitive REs...) make a regexp that ;; is case sensitive or not, regardless of case-fold-search. ;; Input format of lexers: ;; ;; ALIST of the form ((RE . VAL) ...) ;; Format of compiled DFA lexers: ;; ;; nil ; The trivial lexer that fails ;; (CHAR . LEXER) ;; (table . CHAR-TABLE) ;; (stop VAL . LEXER) ; Match the empty string at point or LEXER. ;; (check (PREDICATE . ARG) SUCCESS-LEXER . FAILURE-LEXER) ;; Intermediate NFA nodes may additionally look like: ;; (or LEXERs...) ;; (orelse LEXERs...) ;; (and LEXERs...) ;; (join CONT . EXIT) ;;; Todo: ;; - submatches ;; - backrefs ;; - search rather than just match ;; - extensions: ;; - repeated submatches ;; - negation ;; - lookbehind and lookahead ;; - match(&search?) backward ;; - agrep ;;; Notes ;; Search ;; ------ ;; To turn a match into a search, the basic idea is to use ".*RE" to get ;; a search-DFA as opposed to the match-DFA generated from "RE". ;; Search in Plan9's regexp library is done as follows: match ".*RE" until ;; reaching the first match and then continue with only "RE". The first ;; ".*RE" match corresponds to a search success for the leftmost shortest ;; match. If we want the longest match, we need to continue. But if we ;; continue with ".*RE" then we have no idea when to stop, so we should only ;; continue with "RE". ;; Downside: we may still match things after the "leftmost longest" match, ;; but hopefully will stop soon after. I.e. we may look at chars past the ;; end of the leftmost longest match, but hopefully not too many. ;; Alternatives: ;; - Like emacs/src/regexp.c, we can just start a match at every buffer ;; position. Advantage: no need for submatch info in order to find ;; (match-beginning 0), no need for a separate search-DFA. ;; Downsize: O(N^2) rather than O(N). But it's no worse than what we live ;; with for decades in src/regexp.c. ;; ;; - After the shortest-search, stop the search and do a longest-match ;; starting at position (match-beginning 0). The good thing is that we ;; will not look at any char further than needed. Also we don't need to ;; figure out how to switch from ".*RE" to "RE" in the middle of the sear= ch. ;; The downside is that we end up looking twice at the chars common to the ;; shortest and longest matches. Also this doesn't work: the shortest ;; match may not be the leftmost match, so we can't just start the match ;; at (match-beginning 0). ;; ;; - After the shortest-search, use the submatch data to figure out the NFA ;; states (corresponding to the current search-DFA state) which are only ;; reachable from later starting positions than (match-beginning 0), ;; remove them and figure out from that the match-DFA state to which ;; to switch. Problem is: there might not be any such state in the ;; match-DFA. ;; ;; - Generate a specialized search&match-DFA which encodes the job done by ;; Plan9's regexp library. I.e. do a specialized merge on ;; (or LEXER (anything . LEXER)) where whenever we get a `stop' we don't ;; merge any more. After matching such a lexer, we still have to figure ;; which of the matches we had is the leftmost longest match, of course. ;; Actually, it's not that easy: the tail of a `stop' in the match-DFA can ;; only match things whose (match-beginning 0) may be the same as the one ;; of the `stop', whereas we also want to accept longer matches that start ;; before (match-beginning 0). So we want to keep merging on the tail of ;; `stop' nodes, but only "partially" (whatever that means). ;; Lookahead ;; --------- ;; I suspect that the (?=3D) lookahead can be encoded using something l= ike ;; `andalso'. Of course, it can also trivially be encoded as a predicate, ;; but then we get an O(N^2) complexity. ;;; Code: (eval-when-compile (require 'cl)) (defun copy-char-table (ct1) (let* ((subtype (char-table-subtype ct1)) (ct2 (make-char-table subtype))) (map-char-table (lambda (c v) (set-char-table-range ct2 c v)) ct1) (dotimes (i (or (get subtype 'char-table-extra-slots) 0)) (set-char-table-extra-slot ct2 i (char-table-extra-slot ct1 i))) ct2)) (defun lex--char-table->alist (ct) (let ((res ())) (map-char-table (lambda (k v) (push (cons (if (consp k) ;; If k is a cons cell, we have to ;; copy it because map-char-table ;; reuses it. (cons (car k) (cdr k)) ;; Otherwise, create a trivial cons-cell ;; so we have fewer cases to handle. (cons k k)) v) res)) ct) res)) (defun lex--merge-into (op al1 al2 ct) (assert (memq op '(and or orelse))) ;; We assume that map-char-table calls its function with increasing ;; `key' arguments. (while (and al1 al2) (let ((k1 (caar al1)) (k2 (caar al2))) (cond ;; Perfect overlap. ((equal k1 k2) (set-char-table-range ct k1 (lex--merge op (cdr (pop al1)) (cdr (pop al2)= )))) ;; k1 strictly greater than k2. ((and (consp k1) (consp k2) (> (car k1) (cdr k2))) (let ((v (cdr (pop al1)))) (if (not (eq op 'and)) (set-char-table-range ct k1 v)))) ;; k2 strictly greater than k1. ((and (consp k1) (consp k2) (> (car k2) (cdr k1))) (let ((v (cdr (pop al2)))) (if (not (eq op 'and)) (set-char-table-range ct k2 v)))) ;; There's partial overlap. ((and (consp k1) (consp k2) (> (cdr k1) (cdr k2))) (if (not (eq op 'and)) (set-char-table-range ct (cons (1+ (cdr k2)) (cdr k1)) (cdar al= 1))) (setcdr k1 (cdr k2))) ((and (consp k1) (consp k2) (< (cdr k1) (cdr k2))) (if (not (eq op 'and)) (set-char-table-range ct (cons (1+ (cdr k1)) (cdr k2)) (cdar al= 2))) (setcdr k2 (cdr k1))) ;; Now the tails are equal. ((and (consp k1) (consp k2) (> (car k1) (car k2))) (set-char-table-range ct k1 (lex--merge op (cdr (pop al1)) (cdar al= 2))) (setcdr k2 (1- (car k1)))) ((and (consp k1) (consp k2) (< (car k1) (car k2))) (set-char-table-range ct k2 (lex--merge op (cdar al1) (cdr (pop al2= )))) (setcdr k1 (1- (car k2)))) ((assert nil))))) (if (not (eq op 'and)) (dolist (x (or al1 al2)) (set-char-table-range ct (car x) (cdr x))))) (defvar lex--states) (defvar lex--memoize) (defun lex--set-eq (l1 l2) (let ((len (length l2))) (setq l2 (copy-sequence l2)) (while (consp l1) (assert (=3D len (length l2))) (unless (> len (setq len (length (setq l2 (delq (pop l1) l2))))) (setq l1 t))) (not l1))) (define-hash-table-test 'lex--set-eq 'lex--set-eq (lambda (l) (let ((hash 0)) (while l (let ((x (pop l))) (if (memq x l) (progn (debug) nil) (setq hash (+ hash (sxhash x)))))) hash))) =20=20=20=20=20=20 (defun lex--flatten-state (state) (assert (memq (car state) '(and or orelse))) (let ((op (car state)) (todo (cdr state)) (done (list state)) (res nil)) (while todo (setq state (pop todo)) (cond ((null state) (if (eq op 'and) (setq res nil todo nil))) ((memq state done) nil) ((eq (car-safe state) op) (setq todo (append (cdr state) todo))) (t (unless (memq state res) (push state res))))) (cons op (nreverse res)))) (defun lex--merge-2 (op lex1 lex2) (assert (memq op '(and or orelse))) ;; The order between lex1 and lex2 matters: preference is given to lex1. (cond ((eq lex1 lex2) (debug) lex1) ;CHECK: ruled out by `lex--flatten-state'? ;; ((equal lex1 lex2) lex1) ;Stack overflow :-( ;; Handle the 2 possible nil cases. ;; CHECK: ruled out by `lex--flatten-state'? ((null lex1) (debug) (if (eq op 'and) nil lex2)) ((null lex2) (debug) (if (eq op 'and) nil lex1)) ;; Do the predicate cases before the `stop' because the stop should ;; always come after the checks. ;; TODO: add optimizations for pairs of `checks' which are redundant, ;; or mutually exclusive, ... although we can also do it in lex-optimize. ((and (eq (car lex1) 'check) (eq (car lex2) 'check) (equal (nth 1 lex1) (nth 1 lex2))) ; Same predicate. (list* 'check (nth 1 lex1) (lex--merge op (nth 2 lex1) (nth 2 lex2)) (lex--merge op (nthcdr 3 lex1) (nthcdr 3 lex2)))) ((eq (car lex1) 'check) (list* 'check (nth 1 lex1) (lex--merge op (nth 2 lex1) lex2) (lex--merge op (nthcdr 3 lex1) lex2))) ((eq (car lex2) 'check) (list* 'check (nth 1 lex2) (lex--merge op lex1 (nth 2 lex2)) (lex--merge op lex1 (nthcdr 3 lex2)))) ;; Joins have the form (join CONT . EXIT) where EXIT is a lexer ;; corresponding to the rest of the regexp after the `and' sub-regexp. ;; All the joins corresponding to the same `and' have the same EXIT. ;; CONT is a lexer that contains another join inside, it corresponds to ;; the decision to not yet leave the `and'. ((and (eq (car lex1) 'join) (eq (car lex2) 'join)) (assert (eq (cddr lex1) (cddr lex2))) ;Check they're the same join. `(join ,(lex--merge op (cadr lex1) (cadr lex2)) ,@(cddr lex1))) ;; If one the two lex's is a join but the other not, the other must ;; contain a corresponding join somewhere inside. ((eq (car lex1) 'join) (let ((next (lex--merge op (nth 1 lex1) lex2))) ;; lex1 is a valid exit point but lex2 isn't. (if (eq op 'and) next ;; FIXME: lex1 is implicitly an `or' (or `orelse'?) between (cadr ;; lex1) and (cddr lex1). Here we construct an `or' (or `orelse'?) ;; between `next' and (cddr lex1). I.e. we lose the `op' and we do ;; not preserve the ordering between lex2 and (cddr lex1). `(join ,next ,@(cddr lex1))))) ((eq (car lex2) 'join) (let ((next (lex--merge op lex1 (nth 1 lex2)))) (if (eq op 'and) next `(join ,next ,@(cddr lex2))))) ;; The three `stop' cases. ((and (eq (car lex1) 'stop) (eq (car lex2) 'stop)) ;; Here is where we give precedence to `lex1'. (if (eq op 'orelse) lex1 (list* 'stop (cadr lex1) (lex--merge op (cddr lex1) (cddr lex2))))) ((eq (car lex1) 'stop) (let ((next (lex--merge op (cddr lex1) lex2))) (ecase op (or (list* 'stop (cadr lex1) next)) (orelse lex1) ;; CHECK: We should have hit a `join' before reaching a `stop'. (and (debug) next)))) ((eq (car lex2) 'stop) (let ((next (lex--merge op lex1 (cddr lex2)))) ;; For `orelse', we want here to delay the `stop' until the point ;; where we know that lex1 doesn't match. Sadly, I don't know how to ;; do it. (ecase op ;; CHECK: We should have hit a `join' before reaching a `stop'. (and (debug) next) ;; FIXME: One thing we can do is to mark the value attached to the ;; `stop' so as to indicate that an earlier match may finish later. ;; This way, if the match is not `earlystop', we know it's one of ;; the leftmost ones, and maybe the search loop can avoid some work ;; when determining which is the leftmost longest match. (orelse (list* 'stop `(earlystop ,(cadr lex2)) next)) ((or orelse) (list* 'stop (cadr lex2) next))))) ;; The most general case. ((and (eq (car lex1) 'table) (eq (car lex2) 'table)) (let ((al1 (lex--char-table->alist (cdr lex1))) (al2 (lex--char-table->alist (cdr lex2))) (ct (make-char-table 'lexer))) (lex--merge-into op al1 al2 ct) (cons 'table ct))) ((and (characterp (car lex1)) (characterp (car lex2)) (eq (car lex1) (car lex2))) (cons (car lex1) (lex--merge op (cdr lex1) (cdr lex2)))) ((and (characterp (car lex1)) (characterp (car lex2))) (unless (eq op 'and) (let ((ct (make-char-table 'lexer))) (aset ct (car lex1) (cdr lex1)) (aset ct (car lex2) (cdr lex2)) (cons 'table ct)))) ((and (characterp (car lex1)) (eq (car lex2) 'table)) (let ((next (lex--merge op (cdr lex1) (aref (cdr lex2) (car lex1))))) (if (eq op 'and) (if next (cons (car lex1) next)) (let ((ct (copy-sequence (cdr lex2)))) (aset ct (car lex1) next) (cons 'table ct))))) ((and (eq (car lex1) 'table) (characterp (car lex2))) (let ((next (lex--merge op (aref (cdr lex1) (car lex2)) (cdr lex2)))) (if (eq op 'and) (if next (cons (car lex2) next)) (let ((ct (copy-sequence (cdr lex1)))) (aset ct (car lex2) next) (cons 'table ct))))) ((or (memq (car lex1) '(or orelse and state)) (memq (car lex2) '(or orelse and state))) ;; `state' nodes are nodes whose content is not known yet, so we ;; have to delay the merge via the memoization table. ;; `or' and `and' nodes should only happen when the other `op' is being ;; performed, in which case we can't do the merge either before lex1 ;; and lex2 have both been merged. (lex--merge op lex1 lex2)) ((assert nil)))) (defun lex--merge-now (&rest state) (assert (memq (car state) '(and or orelse))) ;; Re-flatten, in case one of the sub-states was changed. (setq state (lex--flatten-state state)) (if (<=3D (length state) 2) ;; FIXME: for `and' nodes, this is not enough: we need to look for and ;; remove the corresponding `join' node(s). (cadr state) (let ((op (pop state)) (res (pop state))) (dolist (lex state) (setq res (lex--merge-2 op res lex))) (if (and (eq op 'and) (eq (car res) 'join)) ;; Eliminate the join once it was all merged. ;; FIXME: This arbitrarily chooses `or' instead of `orelse', ;; and it arbitrarily gives CONT precedence to EXIT. That doesn't ;; sound right. (lex--merge 'or (cadr res) (cddr res)) res)))) (defun lex--merge (&rest state) (assert (memq (car state) '(and or orelse))) (setq state (lex--flatten-state state)) (if (<=3D (length state) 2) (cadr state) (or (gethash state lex--memoize) (progn ;; (debug) (assert (memq (car state) '(and or orelse))) (push state lex--states) ;; The `state' node will be later on modified via setcar/setcdr, ;; se be careful to use a copy of it for the key. (puthash (cons (car state) (cdr state)) state lex--memoize) state)))) (defun lex--compile-category (category) (if (and (integerp category) (< category 128)) category (if (symbolp category) (if (=3D 1 (length (symbol-name category))) (aref (symbol-name category) 0) (require 'rx) (cdr (assq category rx-categories)))))) (defun lex--compile-syntax (&rest syntaxes) (mapcar (lambda (x) (if (and (integerp x) (< x 32)) x (if (symbolp x) (setq x (if (=3D 1 (length (symbol-name x))) (symbol-name x) (require 'rx) (cdr (assq x rx-syntax))))) (if (characterp x) (setq x (string x))) (car (string-to-syntax x)))) syntaxes)) (defconst lex--char-classes `((alnum alpha digit) (alpha word (?a . ?z) (?A . ?Z)) (blank ?\s ?\t) (cntrl (?\0 . ?\C-_)) (digit (?0 . ?9)) ;; Include all multibyte chars, plus all the bytes except 128-159. (graph (?! . ?~) multibyte (#x3fffa0 . #x3fffff)) ;; src/regexp.c handles case-folding inconsistently: lower and upper ;; match both lower- and uppercase ascii chars, but lower also matches ;; uppercase non-ascii chars whereas upper does not match lowercase ;; nonascii chars. Here I simply ignore case-fold for [:lower:] and ;; [:upper:] because it's simpler and doesn't seem worse. (lower (check (lex--match-lower))) (upper (check (lex--match-upper))) (print graph ?\s) (punct (check (not (lex--match-syntax . ,(lex--compile-syntax "w")))) (?! . ?/) (?: . ?@) (?\[ . ?`) (?\{ . ?~)) (space (check (lex--match-syntax . ,(lex--compile-syntax " ")))) (xdigit digit (?a . ?f) (?A . ?F)) (ascii (?\0 . ?\177)) (nonascii (?\200 . #x3fffff)) (unibyte ascii (#x3fff00 . #x3fffff)) (multibyte (#x100 . #x3ffeff)) (word (check (lex--match-syntax . ,(lex--compile-syntax "w")))) ;; `rx' alternative names. (numeric digit) (num digit) (control cntrl) (hex-digit xdigit) (hex xdigit) (graphic graph) (printing print) (alphanumeric alnum) (letter alpha) (alphabetic alpha) (lower-case lower) (upper-case upper) (punctuation punct) (whitespace space) (white space)) "Definition of char classes. Each element has the form (CLASS . DEFINITION) where definition is a list of elements that can be either CHAR or (CHAR . CHAR), or CLASS (another char class) or (check (PREDICATE . ARG)) or (check (not (PREDICATE . ARG))).") (defvar lex--char-equiv-table nil "Equiv-case table to use to compile case-insensitive regexps.") (defun lex--char-equiv (char) (when lex--char-equiv-table (let ((chars ()) (tmp char)) (while (and (setq tmp (aref lex--char-equiv-table tmp)) (not (eq tmp char))) (push tmp chars)) (if chars (cons char chars))))) =20=20=20=20 (defun lex--nfa (re state) (assert state) ;If `state' is nil we can't match anyway. (cond ((characterp re) (let ((chars (lex--char-equiv re))) (if (null chars) (cons re state) (let ((ct (make-char-table 'lexer))) (dolist (char chars) (aset ct char state)) (cons 'table ct))))) ((stringp re) (if (null lex--char-equiv-table) ;; (Very) minor optimization. (nconc (mapcar 'identity re) state) (lex--nfa `(seq ,@(mapcar 'identity re)) state))) (t (ecase (or (car-safe re) re) ((: seq sequence ;; Hack! group) (dolist (elem (reverse (cdr re))) (setq state (lex--nfa elem state))) state) ((char in not-char) (let ((chars (cdr re)) (checks nil) (fail nil) (char nil) ;The char seen, or nil if none, or t if more than o= ne. (ct (make-char-table 'lexer))) (when (or (eq 'not (car chars)) (eq 'not-char (car re))) (setq chars (cdr chars)) (set-char-table-range ct t state) (setq fail state) (setq state nil)) (while chars (let ((range (pop chars))) (cond ((stringp range) (setq chars (append (cdr (lex--parse-charset range)) chars))) ((symbolp range) (setq range (or (cdr (assq range lex--char-classes)) (error "Uknown char class `%s'" range))) (setq chars (append range chars))) ((and (consp range) (eq 'check (car range))) (push (cadr range) checks)) (t (setq char (if (or char (not (characterp range)) (and lex--char-equiv-table (lex--char-equiv range))) t range)) ;; Set the range, first, regardless of case-folding. This is ;; important because case-tables like to be set with few ;; large ranges rather than many small ones, as is done in ;; the case-fold loop. (set-char-table-range ct range state) (when (and lex--char-equiv-table ;; Avoid looping over all characters. (not (equal range '(#x100 . #x3ffeff)))) ;; Add all the case-equiv chars. (let ((i (if (consp range) (car range) range)) (max (if (consp range) (cdr range) range)) char) (while (<=3D i max) (setq char i) (while (and (setq char (aref lex--char-equiv-table cha= r)) (not (eq char i))) (aset ct char state)) (setq i (1+ i))))))))) (let ((res (if (or (eq char t) fail) (cons 'table ct) (if char (cons char state))))) (if (and (not fail) checks) (setq state (lex--nfa 'anything state))) (dolist (check checks) (setq res (if fail ;; We do an `and' of the negation of the check and r= es. (if (eq (car-safe check) 'not) (list 'check (cadr check) res) (list* 'check check nil res)) ;; An `or' of the check and res. (if (eq (car-safe check) 'not) (list 'check (cadr check) res state) (list* 'check check state res))))) res))) ((union or | orelse) (apply 'lex--merge (if (eq (car re) 'orelse) 'orelse 'or) (mapcar (lambda (re) (lex--nfa re state)) (cdr re)))) ((inter intersection &) ;; Just using `and' is not enough because we have to enforce that the ;; sub-regexps (rather than the whole regexp) match the same string. ;; So we need to mark the juncture point. (let* ((join `(join nil ,@state))) (apply 'lex--merge 'and (mapcar (lambda (re) (lex--nfa re join)) (cdr re))))) ((0+ zero-or-more * *\?) (let ((newstate (list 'state))) (let ((lexer (lex--nfa (cons 'seq (cdr re)) newstate))) (setcdr newstate (if (memq (car re) '(*\?)) (list state lexer) (list lexer state)))) (setcar newstate (if (memq (car re) '(*\?)) 'orelse 'or)) (assert (memq (car newstate) '(and or orelse))) (push newstate lex--states) newstate)) =20=20=20=20=20=20 ((string-end eos eot buffer-end eob) `(check (lex--match-eobp) ,state= )) ((string-start bos bot buffer-start bob) `(check (lex--match-bobp) ,state)) ((line-end eol) `(check (lex--match-eolp) ,state)) ((line-start bol) `(check (lex--match-bolp) ,state)) ((word-start bow) `(check (lex--match-bowp) ,state)) ((word-end eow) `(check (lex--match-eowp) ,state)) ((symbol-start) `(check (lex--match-bosp) ,state)) ((symbol-end) `(check (lex--match-eosp) ,state)) ((not-word-boundary) `(check (lex--match-not-word-boundary) ,state)) ((word-boundary) `(check (lex--match-not-word-boundary) nil . ,state)) ((syntax) `(check (lex--match-syntax . ,(apply 'lex--compile-syntax (cdr re))) ,(lex--nfa 'anything state))) ((not-syntax) `(check (lex--match-syntax . ,(apply 'lex--compile-syntax (cdr re))) nil . ,(lex--nfa 'anything state))) ((category) `(check (lex--match-category . ,(lex--compile-category (cadr re))) ,(lex--nfa 'anything state))) ((not-category) `(check (lex--match-category . ,(lex--compile-category (cadr re))) nil . ,(lex--nfa 'anything state))) =20=20=20=20=20=20 ;; `rx' accepts char-classes directly as regexps. Let's reluctantly ;; do the same. ((digit numeric num control cntrl hex-digit hex xdigit blank graphic graph printing print alphanumeric alnum letter alphabetic alpha asc= ii nonascii lower lower-case upper upper-case punctuation punct space whitespace white) (lex--nfa `(char ,re) state)) ((case-sensitive) (let ((lex--char-equiv-table nil)) (lex--nfa `(seq ,@(cdr re)) state))) ((case-fold) (let ((lex--char-equiv-table (get-eqvcase-table (current-case-table)= ))) (lex--nfa `(seq ,@(cdr re)) state))) ((point ;; Sub groups! submatch group backref ;; Greediness control minimal-match maximal-match) (error "`%s' Not implemented" (or (car-safe re) re))) ((not-newline nonl dot) (lex--nfa '(char not ?\n) state)) (anything (lex--nfa '(char not) state)) ((word wordchar) (lex--nfa '(syntax w) state)) ((not-wordchar) (lex--nfa '(not-syntax w) state)) (any ;; `rx' uses it for (char ...) sets, and sregex uses it for `dot'. (lex--nfa (if (consp re) (cons 'char (cdr re)) '(char not ?\n)) stat= e)) (not ;; The `not' as used in `rx' should be deprecated: we may want to ;; provide real support for a fully general `not', but its semantics ;; will most likely be different. E.g. we may want to let ;; (not (char ...)) match the empty string. (setq re (cadr re)) (ecase (or (car-safe re) re) (word-boundary (message "`not' deprecated: use not-word-boundary") (lex--nfa 'not-word-boundary state)) ((any in char) (message "`not' deprecated: use (%s not ...)" (or (car-safe re) r= e)) (lex--nfa (list* (car re) 'not (cdr re)) state)) ((category syntax) (message "`not' deprecated: use not-%s" (car re)) (lex--nfa (cons (intern (format "not-%s" (car re))) (cdr re)) sta= te)))) (and ;; `rx' defined `and' as `sequence', but we may want to define it ;; as intersection instead. (error "`and' is deprecated, use `seq', `:', or `sequence' instead")) =20=20=20=20=20=20=20=20=20 ((1+ one-or-more + +\?) (lex--nfa `(seq (seq ,@(cdr re)) (,(if (memq (car re) '(+\?)) '*\? '0+) ,@(cdr re))) state)) ((opt zero-or-one optional \?) (lex--nfa `(or (seq ,@(cdr re)) "") state)) ((\?\?) (lex--nfa `(orelse "" (seq ,@(cdr re))) state)) ((repeat ** =3D) (let ((min (nth 1 re)) (max (nth 2 re)) (res (nthcdr 3 re))) (unless res (setq res (list max)) (setq max min)) (lex--nfa `(seq ,@(append (make-list (or min 0) (if (eq (length res) 1) (car res) (cons 'seq res))) (if (null max) `((0+ ,@res)) (make-list (- max (or min 0)) `(opt ,@res))))) state))) ((>=3D) (lex--nfa `(repeat ,(nth 1 re) nil ,@(nthcdr 2 re)) state)) ((bre re ere) (lex--nfa (lex-parse-re (nth 1 re) (car re)) state)))))) (defun lex--dfa-wrapper (f) (let* ((lex--states ()) (lex--memoize (make-hash-table :test 'lex--set-eq)) (res (funcall f)) (postponed ()) (states-dfa (make-hash-table :test 'eq))) (while lex--states (dolist (state (prog1 lex--states (setq lex--states nil))) (let ((merged (apply 'lex--merge-now state))) (if (memq (car merged) '(and or orelse)) ;; The merge could not be performed for some reason: ;; let's re-schedule it. (push state postponed) (puthash state merged states-dfa)))) (unless lex--states ;; If states-dfa is empty it means we haven't made any progress, ;; so we're stuck in an infinite loop. Hopefully this cannot happe= n? (assert (not (zerop (hash-table-count states-dfa)))) (maphash (lambda (k v) (unless v ;; With `intersection', lex--merge may end up returning ;; nil if the intersection is empty, so `v' can be ;; nil here. In since `k' is necessarily a cons cell, ;; we can't turn it into nil, so we turn it into ;; a more costly lexer that also fails for all inputs. (setq v '(?a))) (setcar k (car v)) (setcdr k (cdr v))) states-dfa) (clrhash states-dfa) (setq lex--states postponed) (setq postponed nil))) res)) (defun lex-compile (alist) (lex--dfa-wrapper (lambda () (let ((lex--char-equiv-table (if case-fold-search (get-eqvcase-table (current-case-table))))) (apply 'lex--merge 'or (mapcar (lambda (x) (lex--nfa (car x) (list 'stop (cdr x)))) alist)))))) (defun lex-search-dfa (match-dfa) ;; This constructs a search-DFA whose last match should be the leftmost ;; longest match. (lex--dfa-wrapper (lambda () (lex--nfa '(*\? (char not)) match-dfa)))) (defun lex--terminate-if (new old) (cond ((eq new t) t) ((eq old t) t) (t (while new (let ((x (pop new))) (if (memq x old) (push x old)))) old)= )) (defun lex--optimize-1 (lexer) (let ((terminate nil)) (cons (case (car lexer) (table (let ((ct (cdr lexer)) (char nil)) ;; Optimize each entry. (map-char-table (lambda (range v) (let ((cell (lex--optimize v))) (setq terminate (lex--terminate-if (cdr cell) terminate)) (set-char-table-range ct range (car cell)))) ct) ;; Optimize the internal representation of the table. (optimize-char-table (cdr lexer)) ;; Eliminate the table if possible. (map-char-table (lambda (range v) (setq char (if (and (characterp range) (null char)) range t))) ct) (case char ((nil) nil) ((t) lexer) (t (setcar lexer 'char) (setcdr lexer (aref ct char)) lexer)))) (stop (let ((cell (lex--optimize (cddr lexer)))) (setq terminate t) (setf (cddr lexer) (car cell))) lexer) (check (let* ((test (nth 1 lexer)) (cellf (lex--optimize (nthcdr 3 lexer))) (fail (setf (nthcdr 3 lexer) (car cellf))) (cells (lex--optimize (nth 2 lexer))) (succ (setf (nth 2 lexer) (car cells)))) (setq terminate (lex--terminate-if (cdr cellf) terminate)) (setq terminate (lex--terminate-if (cdr cells) terminate)) (when (eq 'check (car succ)) (cond ((equal test (nth 1 succ)) ;Same successful test. (debug) (setf (nth 2 lexer) (setq succ (nth 2 succ)))) ;; TODO: we can add rules such as bobp -> eolp, ;; bosp -> bowp, (syntax X) -> (syntax Y X), ... )) (when (eq 'check (car fail)) (cond ((equal test (nth 1 fail)) ;Same failing test. (debug) (setf (nthcdr 3 lexer) (setq fail (nthcdr 3 succ)))) ;; TODO: we can add rules such as !eolp -> !bobp, ;; !bowp -> !bosp, !(syntax Y X) -> !(syntax X), ... )) (if (or succ fail) lexer))) (t (assert (characterp (car lexer))) (let ((cell (lex--optimize (cdr lexer)))) (setq terminate (lex--terminate-if (cdr cell) terminate)) (if (setf (cdr lexer) (car cell)) lexer)))) (if (consp terminate) (delq lexer terminate) terminate)))) (defun lex--optimize (lexer) (when lexer ;; The lex--memoize cache maps lexer states to (LEXER . TERMINATE) where ;; TERMINATE is either t to say that LEXER can terminate or a list of ;; lexers which means that LEXER terminates only if one of the lexers in ;; the list terminates. (let ((cache (gethash lexer lex--memoize))) (if cache ;; Optimize (char C) to nil. (if (and (characterp (caar cache)) (null (cdar cache))) nil cache) ;; Store a value indicating that we're in the process of computing = it, ;; so when we encounter a loop, we don't recurse indefinitely. ;; Not knowing any better, we start by stating the tautology that ;; `lexer' terminates if and only if `lexer' terminates. (let ((cell (cons lexer (list lexer)))) (puthash lexer cell lex--memoize) (let ((res (lex--optimize-1 lexer))) (if (and (car res) (cdr res)) res (setcar lexer ?a) (setcdr lexer nil) (puthash lexer '(nil) lex--memoize) nil))))))) (defun lex-optimize (lexer) (let ((lex--memoize (make-hash-table :test 'eq))) (prog1 (car (lex--optimize lexer)) (message "Visited %d states" (hash-table-count lex--memoize))))) (defmacro lex-case (object posvar &rest cases) (declare (indent 2)) (let* ((i -1) (alist (mapcar (lambda (case) (cons (car case) (incf i))) cases)) (lex (lex-compile alist)) (tmpsym (make-symbol "tmp"))) (setq i -1) `(let ((,tmpsym (lex-match-string ',lex ,object ,posvar))) (case (cdr ,tmpsym) ,@(mapcar (lambda (case) `(,(incf i) (set-match-data (list ,posvar (setq ,posvar (car ,tmpsym)= ))) ,@(cdr case))) cases))))) ;;; Matching engine (defun lex--match-bobp (arg pos &optional string) (=3D pos (if string 0 (point-min)))) (defun lex--match-eobp (arg pos &optional string) (=3D pos (if string (length string) (point-max)))) (defun lex--match-bolp (arg pos &optional string) (if string (or (=3D pos 0) (eq ?\n (aref string (1- pos)))) (memq (char-before pos) '(nil ?\n)))) (defun lex--match-eolp (arg pos &optional string) (if string (or (=3D pos (length string)) (eq ?\n (aref string pos))) (memq (char-after pos) '(nil ?\n)))) (defun lex--match-bowp (arg pos &optional string) (and (not (if string (and (> pos 0) (eq ?w (char-syntax (aref string (1- pos))))) (and (> pos (point-min)) (eq 2 (car (syntax-after (1- pos))))= ))) (if string (and (< pos (length string)) (eq ?w (char-syntax (aref string pos)))) (eq 2 (car (syntax-after pos)))))) (defun lex--match-eowp (arg pos &optional string) (and (if string (and (> pos 0) (eq ?w (char-syntax (aref string (1- pos))))) (and (> pos (point-min)) (eq 2 (car (syntax-after (1- pos)))))) (not (if string (and (< pos (length string)) (eq ?w (char-syntax (aref string pos)))) (eq 2 (car (syntax-after pos))))))) (defun lex--match-bosp (arg pos &optional string) (and (not (if string (and (> pos 0) (memq (char-syntax (aref string (1- pos))) '(?w ?_))) (and (> pos (point-min)) (memq (car (syntax-after (1- pos))) '(2 3))))) (if string (and (< pos (length string)) (memq (char-syntax (aref string pos)) '(?w ?_))) (memq (car (syntax-after pos)) '(2 3))))) (defun lex--match-eosp (arg pos &optional string) (and (if string (and (> pos 0) (memq (char-syntax (aref string (1- pos))) '(?w ?_))) (and (> pos (point-min)) (memq (car (syntax-after (1- pos))) '(2 3= )))) (not (if string (and (< pos (length string)) (memq (char-syntax (aref string pos)) '(?w ?_))) (memq (car (syntax-after pos)) '(2 3)))))) (defun lex--match-not-word-boundary (arg pos &optional string) (eq (if string (and (> pos 0) (eq ?w (char-syntax (aref string (1- pos))))) (and (> pos (point-min)) (eq 2 (car (syntax-after (1- pos)))))) (if string (and (< pos (length string)) (eq ?w (char-syntax (aref string pos)))) (eq 2 (car (syntax-after pos)))))) (defun lex--match-upper (arg pos &optional string) (when (< pos (if string (length string) (point-max))) (let ((char (if string (aref string pos) (char-after pos)))) (not (eq (downcase char) char))))) (defun lex--match-lower (arg pos &optional string) (when (< pos (if string (length string) (point-max))) (let ((char (if string (aref string pos) (char-after pos)))) (not (eq (upcase char) char))))) (defun lex--match-category (category pos &optional string) (when (< pos (if string (length string) (point-max))) (aref (char-category-set (if string (aref string pos) (char-after pos))) category))) (defun lex--match-syntax (syntaxes pos &optional string) (when (< pos (if string (length string) (point-max))) (memq (car (if string (aref (syntax-table) (aref string pos)) (syntax-after pos))) syntaxes))) (defun lex-match-string (lex string &optional start) ;; FIXME: Move this to C. (unless start (setq start 0)) (let ((match nil)) (while (progn (while (eq (car lex) 'check) (setq lex (if (funcall (car (nth 1 lex)) (cdr (nth 1 lex)) start string) (nth 2 lex) (nthcdr 3 lex)))) (when (eq (car lex) 'stop) (setq match (cons start (cadr lex))) (message "Found match: %s" match) (setq lex (cddr lex))) (assert (not (eq (car lex) 'stop))) (and lex (< start (length string)))) (let ((c (aref string start))) (setq start (1+ start)) (setq lex (cond ((eq (car lex) 'table) (aref (cdr lex) c)) ((integerp (car lex)) (if (eq c (car lex)) (cdr lex))))= ))) (message "Final search pos considered: %s" start) match)) =20=20=20=20=20=20=20=20 ;;; Regexp parsers. (defun lex--tokenizer (lex string) (let ((tokens ()) (i 0) tmp) (while (and (< i (length string)) (setq tmp (lex-match-string lex string i))) (push (cons (cdr tmp) (substring string i (setq i (car tmp)))) tokens= )) (nreverse tokens))) (defun lex--parse-charset (string) (let ((i 0) (ranges ())) (when (eq (aref string i) ?^) (push 'not ranges) (setq i (1+ i))) (let ((op nil) (case-fold-search nil)) (while (not (eq op 'stop)) (lex-case string i ((seq "[:" (0+ (char (?a . ?z) (?A . ?Z))) ":]") (push (intern (substring string (+ 2 (match-beginning 0)) (- (match-end 0) 2))) ranges)) ((seq anything "-" anything) (push (cons (aref string (match-beginning 0)) (aref string (1- (match-end 0)))) ranges)) (anything (push (aref string (1- (match-end 0))) ranges)) (eob (setq op 'stop)))) =20=20=20=20=20=20 `(char ,@(nreverse ranges))))) (defconst lex--parse-re-lexspec '(((or "*" "+" "?" "*?" "+?" "??") . suffix) ((seq "[" (opt "^") (opt "]") (0+ (or (seq (char not ?\]) "-" (char not ?\])) (seq "[:" (1+ (char (?a . ?z) (?A . ?Z))) ":]") (char not ?\]))) "]") . charset) ((seq "\\c" anything) . category) ((seq "\\C" anything) . not-category) ((seq "\\s" anything) . syntax) ((seq "\\S" anything) . not-syntax) ((seq "\\" (char (?1 . ?9))) . backref) ("\\'" . eob) ("\\`" . bob) ("." . dot) ("^" . bol) ("$" . eol) ("." . dot) ("\\<" . bow) ("\\>" . eow) ("\\_<" . symbol-start) ("\\_>" . symbol-end) ("\\w" . wordchar) ("\\W" . not-wordchar) ("\\b" . word-boundary) ("\\B" . not-word-boundary) ("\\=3D" . point) ((or (seq ?\\ anything) anything) . char))) =20=20 (defconst lex--parse-ere-lexer (let ((case-fold-search nil)) (lex-compile (append '(("(?:" . shy-group) ("|" . or) ((seq "{" (0+ (char (?0 . ?9))) (opt (seq "," (0+ (char (?0 . ?9))))) "}") . repeat) ((or ")" eob) . stop) ("(" . group)) lex--parse-re-lexspec)))) (defconst lex--parse-bre-lexer (let ((case-fold-search nil)) (lex-compile (append '(("\\(?:" . shy-group) ("\\|" . or) ((seq "\\{" (0+ (char (?0 . ?9))) (opt (seq "," (0+ (char (?0 . ?9))))) "\\}") . repeat) ((or "\\)" eob) . stop) ("\\(" . group)) lex--parse-re-lexspec)))) (defun lex--parse-re (string i lexer) (let ((stack ()) (op nil) (res nil) tmp) (while (and (not (eq op 'stop)) (setq tmp (lex-match-string lexer string i))) (ecase (cdr tmp) (shy-group (setq tmp (lex--parse-re string (car tmp) lexer)) (unless (eq (aref string (1- (car tmp))) ?\)) (error "Unclosed shy-group")) (push (cdr tmp) res)) (group (setq tmp (lex--parse-re string (car tmp) lexer)) (unless (eq (aref string (1- (car tmp))) ?\)) (error "Unclosed shy-group")) (push (list 'group (cdr tmp)) res)) (suffix (if (null res) (error "Non-prefixed suffix operator") (setq res (cons (list (cdr (assoc (substring string i (car tmp)) '(("*" . 0+) ("+" . 1+) ("?" . opt) ("*?" . *\?) ("+?" . +\?) ("??" . \?\?)))) (car res)) (cdr res))))) (or (push `(or (seq ,@(nreverse res))) stack) (setq res nil)) (charset (push (lex--parse-charset (substring string (1+ i) (1- (car tmp)))) res)) (repeat ;; Here we would like to have sub-matches :-( (let* ((min (string-to-number (substring string (+ i (if (eq (aref string i) ?\\) 2= 1)) (car tmp)))) (max (let ((comma (string-match "," string i))) (if (not (and comma (< comma (car tmp)))) min (if (=3D comma (- (car tmp) 2)) nil (string-to-number (substring string (1+ comma)))= ))))) (if (null res) (error "Non-prefixed repeat operator") (setq res (cons `(repeat ,min ,max ,(car res)) (cdr res)))))) (stop (setq op 'stop)) ((syntax category not-syntax not-category) (push (list (cdr tmp) (aref string (1- (car tmp)))) res)) (backref (push (list (cdr tmp) (- (aref string (1- (car tmp))) ?0)) res)) (char (push (aref string (1- (car tmp))) res)) (t (push (cdr tmp) res))) (setq i (car tmp))) (let ((re `(seq ,@(nreverse res)))) (while stack (setq re (nconc (pop stack) (list re)))) (cons i re)))) (defun lex-parse-re (string &optional lexer) (setq lexer (cond ((eq lexer 'ere) lex--parse-ere-lexer) ((memq lexer '(bre re nil)) lex--parse-bre-lexer) (t lexer))) (let ((res (lex--parse-re string 0 lexer))) (if (< (car res) (length string)) (error "Regexp parsing failed around %d: ...%s..." (substring string (1- i) (1+ i))) (cdr res)))) ;; (defun lex--parse-re (string i) ;; (let ((stack ()) ;; (op nil) ;; (res nil)) ;; (while (and (not (eq op 'stop))) ;; (lex-case string i ;; ("(?:" ;shy-group. ;; (let ((tmp (lex--parse-re string i))) ;; (setq i (car tmp)) ;; (unless (eq (aref string (1- i)) ?\)) (error "Unclosed shy-gr= oup")) ;; (push (cdr tmp) res))) ;; ((or "*?" "+?" "??") ;; (error "Greediness control unsupported `%s'" (match-string 0 st= ring))) ;; ((or "*" "+" "?") ;; (if (null res) (error "Non-prefixed suffix operator") ;; (setq res (cons (list (cdr (assq (aref string (1- i)) ;; '((?* . 0+) ;; (?+ . 1+) ;; (?? . opt)))) ;; (car res)) ;; (cdr res))))) ;; ("|" (push `(or (seq ,@(nreverse res))) stack) ;; (setq res nil)) ;; ((seq "[" (opt "^") (opt "]") ;; (0+ (or (seq (char not ?\]) "-" (char not ?\])) ;; (seq "[:" (1+ (char (?a . ?z) (?A . ?Z))) ":]= ") ;; (char not ?\]))) "]") ;; (push (lex--parse-charset ;; (substring string (1+ (match-beginning 0)) ;; (1- (match-end 0)))) ;; res)) ;; ((seq "{" (0+ (char (?0 . ?9))) ;; (opt (seq "," (0+ (char (?0 . ?9))))) "}") ;; ;; Here we would like to have sub-matches :-( ;; (let* ((min (string-to-number (substring string ;; (1+ (match-beginning 0= )) ;; (match-end 0)))) ;; (max (let ((comma (string-match "," string (match-beginn= ing 0)))) ;; (if (not (and comma (< comma (match-end 0)))) ;; min ;; (if (=3D comma (- (match-end 0) 2)) ;; nil ;; (string-to-number (substring string (1+ comma= )))))))) ;; (if (null res) (error "Non-prefixed repeat operator") ;; (setq res (cons `(repeat ,min ,max ,(car res)) (cdr res))))= )) ;; ((or ")" eob) (setq op 'stop)) ;; ("\\'" (push 'eob res)) ;; ("\\`" (push 'bob res)) ;; ("^" (push 'bol res)) ;; ("$" (push 'eol res)) ;; ("." (push 'dot res)) ;; ((or "(" "\\<" "\\>" "\\_<" "\\_>" "\\c" "\\s" "\\C" "\\S" "\\w"= "\\W" ;; "\\b" "\\B" "\\=3D" (seq "\\" (char (?1 . ?9)))) ;; (error "Unsupported construct `%s'" (match-string 0 string))) ;; ((or (seq ?\\ anything) anything) ;; (push (aref string (1- (match-end 0))) res)) ;; ("" (error "This should not be reachable")))) ;; (let ((re `(seq ,@(nreverse res)))) ;; (while stack (setq re (nconc (pop stack) (list re)))) ;; (cons i re)))) (provide 'lex) ;;; lex.el ends here --=-=-=-- From unknown Fri Jun 20 19:54:56 2025 X-Loop: don@donarmstrong.com Subject: bug#192: regexp does not work as documented Reply-To: Stefan Monnier , 192@debbugs.gnu.org Resent-From: Stefan Monnier Resent-To: bug-submit-list@lists.donarmstrong.com Resent-CC: Emacs Bugs Resent-Date: Mon, 12 May 2008 01:50:02 +0000 Resent-Message-ID: Resent-Sender: don@donarmstrong.com X-Emacs-PR-Message: report 192 X-Emacs-PR-Package: emacs X-Emacs-PR-Keywords: Received: via spool by 192-submit@emacsbugs.donarmstrong.com id=B192.121055663712965 (code B ref 192); Mon, 12 May 2008 01:50:02 +0000 X-Spam-Checker-Version: SpamAssassin 3.2.3-bugs.debian.org_2005_01_02 (2007-08-08) on rzlab.ucr.edu X-Spam-Level: X-Spam-Status: No, score=0.4 required=4.0 tests=AWL autolearn=ham version=3.2.3-bugs.debian.org_2005_01_02 Received: (at 192) by emacsbugs.donarmstrong.com; 12 May 2008 01:43:57 +0000 Received: from ironport2-out.teksavvy.com (ironport2-out.teksavvy.com [206.248.154.182]) by rzlab.ucr.edu (8.13.8/8.13.8/Debian-3) with ESMTP id m4C1hrQg012959 for <192@emacsbugs.donarmstrong.com>; Sun, 11 May 2008 18:43:54 -0700 X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: AmoCAIM9J0jO+JgrdGdsb2JhbACBU5A6ASeXEA X-IronPort-AV: E=Sophos;i="4.27,470,1204520400"; d="scan'208";a="20309136" Received: from smtp.pppoe.ca (HELO smtp.teksavvy.com) ([65.39.196.238]) by ironport2-out.teksavvy.com with ESMTP; 11 May 2008 21:43:48 -0400 Received: from pastel.home ([206.248.152.43]) by smtp.teksavvy.com (Internet Mail Server v1.0) with ESMTP id SGD37548; Sun, 11 May 2008 21:43:48 -0400 Received: by pastel.home (Postfix, from userid 20848) id E689E7F83; Sun, 11 May 2008 21:43:47 -0400 (EDT) From: Stefan Monnier To: Thomas Lord Cc: Chong Yidong , martin rudalics , David Koppelman , 192@debbugs.gnu.org, Bruno Haible , emacs-devel@gnu.org Message-ID: References: <87k5i8ukq8.fsf@stupidchicken.com> <200805061335.11379.bruno@clisp.org> <48204B3D.6000500@gmx.at> <4826A303.3030002@gmx.at> <87abiwoqzd.fsf@stupidchicken.com> <482750F4.2050102@emf.net> Date: Sun, 11 May 2008 21:43:47 -0400 In-Reply-To: <482750F4.2050102@emf.net> (Thomas Lord's message of "Sun, 11 May 2008 13:03:00 -0700") User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/23.0.60 (gnu/linux) MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii > Well, instead of using heuristics to decide where to re-scan from and > too, you can cache a record of where the DFA scan arrived at for > periodic positions in the buffer. Then begin scanning from just > before any modification for as far as it takes to arrive at a DFA > state that is the same as last time, updating any highlighting in the > region between those two points. That's a very good point. I'm not sure it's worth the trouble to store it at various buffer positions and check if it's EQ to stop the rescan, but at least we could match multiline expression one-line at a time. In any case, it's indeed a non-trivial amount of work because it probably requires rewriting not just font-lock but all the foo-mode-font-lock-keywords as well (font-lock-keywords are order dependent so you can't apply the rule nb 3 after rule nb 4). > I don't mean to imply that this is a trivial thing to implement in > Emacs but if you start getting up to building DFAs (very expensive in > the worst case) and taking intersections (very expensive in the worst > case) -- both also not all that simple to implement (nor obviously > possible for Emacs' extended regexp language) -- then the effort may > be comparable and (re-)visiting the option to adapt Rx to Emacs should > be worth considering. I have most of the DFA construction code written, but I may take you up on that anyway. BTW, regarding the "very expensive in the worst case", how common is this worst case in real life? Stefan From unknown Fri Jun 20 19:54:56 2025 X-Loop: don@donarmstrong.com Subject: bug#192: regexp does not work as documented Reply-To: Thomas Lord , 192@debbugs.gnu.org Resent-From: Thomas Lord Resent-To: bug-submit-list@lists.donarmstrong.com Resent-CC: Emacs Bugs Resent-Date: Mon, 12 May 2008 02:55:03 +0000 Resent-Message-ID: Resent-Sender: don@donarmstrong.com X-Emacs-PR-Message: report 192 X-Emacs-PR-Package: emacs X-Emacs-PR-Keywords: Received: via spool by 192-submit@emacsbugs.donarmstrong.com id=B192.121056041522754 (code B ref 192); Mon, 12 May 2008 02:55:03 +0000 X-Spam-Checker-Version: SpamAssassin 3.2.3-bugs.debian.org_2005_01_02 (2007-08-08) on rzlab.ucr.edu X-Spam-Level: X-Spam-Status: No, score=0.8 required=4.0 tests=AWL,SPF_HELO_PASS autolearn=ham version=3.2.3-bugs.debian.org_2005_01_02 Received: (at 192) by emacsbugs.donarmstrong.com; 12 May 2008 02:46:55 +0000 Received: from mail.42inc.com (mail.42inc.com [205.149.0.25]) by rzlab.ucr.edu (8.13.8/8.13.8/Debian-3) with ESMTP id m4C2kpBt022748 for <192@emacsbugs.donarmstrong.com>; Sun, 11 May 2008 19:46:52 -0700 X-TFF-CGPSA-Version: 1.5 X-TFF-CGPSA-Filter-42inc: Scanned X-42-Virus-Scanned: by 42 Antivirus -- Found to be clean. Received: from [69.236.114.9] (account lord@emf.net HELO [192.168.1.64]) by mail.42inc.com (CommuniGate Pro SMTP 5.0.13) with ESMTPA id 30307698; Sun, 11 May 2008 19:46:49 -0700 Message-ID: <4827B9B8.30406@emf.net> Date: Sun, 11 May 2008 20:30:00 -0700 From: Thomas Lord User-Agent: Thunderbird 1.5.0.5 (X11/20060808) MIME-Version: 1.0 To: Stefan Monnier CC: Chong Yidong , martin rudalics , David Koppelman , 192@debbugs.gnu.org, Bruno Haible , emacs-devel@gnu.org References: <87k5i8ukq8.fsf@stupidchicken.com> <200805061335.11379.bruno@clisp.org> <48204B3D.6000500@gmx.at> <4826A303.3030002@gmx.at> <87abiwoqzd.fsf@stupidchicken.com> <482750F4.2050102@emf.net> In-Reply-To: Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit Stefan Monnier wrote: > I have most of the DFA construction code written, but I may take you up > on that anyway. BTW, regarding the "very expensive in the worst case", > how common is this worst case in real life? > Talking about general purpose use of an engine, as opposed to something more narrow like "likely font-lock expressions": It's common enough in "real life" (in my experience) to be exactly the minimal amount required to make it annoying. Let me give you some rules of thumb to describe what I mean but I'll refrain from a long treatise explaining the theory that supports these. If you have questions I can "unpack" this on list or off. First, be careful to make a clear distinction between (let's dub the distinction) "regexps vs. regular expressions". "Regular expressions" correspond to formally regular languages. Regular expressions can always be converted to a DFA. "regexps" are what most people use in most situations. regexps include things like features to extract the positions that match a sub-pattern. regexps do *not* correspond to regular languages and *can not* always be converted to DFA. DFA conversion can help with regexp matching, but it can't solve it completely. Moreover, you can make pathological regexps (very slow to match) for every regexp I know of. Henry Spencer (I've heard) asserts that regexps are NP complete or something around there, though I haven't seen the proof. (Rx is a hybrid regular expression and regexp engine based on an on-line (caching, incremental) DFA conversion suggested in the "Dragon" compiler book and originating from (as I recall) an experiment by Thompson and one of the other Bell Labs guys. One of whoever it was privately mentioned that they abandoned it themselves because it was taking too much code to implement, or something like that.) That aside, regular expressions are probably plenty for font-lock functionality, so let's just talk about those. On-line DFA conversion for those is likely practical by multiple means. The size of a DFA is, worst-case, exponential in the size of the regular expression. This is the source of pathological cases that can thwart any DFA engine. (In exponential cases, Rx keeps running but more like an NFA, taking a corresponding performance hit.) For a time, I was pushing hard on Rx, trying to use it for absolutely everything. To make up new problems to solve as in "Ok, let's suppose I can run X-Kbyte long regular expressions with lots of | operators, stars, etc. What can I apply that to?" One example is lexing for real-world computer languages. [Aside: you can also use the same engine as the core of a shift-reduce parser, of course -- and I did that a long time ago with Guile, to useful effect.] Almost always, the expressions were such that Rx would have no problem and give very pleasing results. However, there were definitely times (for huge regular expressions and smaller ones) when things would just absolutely crawl. They happen "just often enough" to be an annoyance. Now, every case of that annoyance that I found (in real-life applications) had a solution. I could think for a while on *why* the regular expression I wrote was blowing up and then think of a different approach that eliminated the problem. Most often that meant not a different but equivalent regular expression -- it meant going one level up and changing the way the caller used regular expressions. The caller would retain the same functionality but different demands would be made on the regular expression (or regexp) engine. And that makes it tricky to drop *blindly* into Emacs. To solve the unavoidable annoying cases you really had to know how regular expressions worked at a deep level. To diagnose and work around the pathological cases took some expertise. As a general rule, for something "general purpose" like a libc implementation or the default regexp functions in Emacs lisp, there is something to be said for using NFA matchers. It's perverse why: Vast swaths of things that a DFA matcher can do very quickly an NFA matcher can not. It's reliably slow. Therefore, people not prepared to think hard about regexps tend to use an NFA matcher in pretty limited ways. A powerful regular expression engine could simplify their code, at the cost of risking finding a "hard case" -- but there's no issue since people quickly give up and don't try to push the match engine that hard. More concisely: If you use a DFA matcher You Better Know What You're Doing but also Most of the Time You Won't Need To So It's Very Convenient. If you use an NFA matcher You Can Get Away With Not Really Knowing What You're Doing but also You Won't Be Trying Anything Fancy, Perhaps Losing Out. One approach to toss into the mix, this one suggested by Per Bothner years ago, is to consider *offline* DFA conversion (a la 'lex(1)'). The advantage of offline (batch) conversion is that you can burn a lot of cycles on DFA minimization and, if your offline converter terminates, you've got a reliably linear matcher. The disadvantages for *many* uses of regular expressions in Emacs should be pretty obvious. For something like font-lock, where the regular expressions don't change that often, that might be a good approach -- precompile a minimal DFA and then add support for "regular expression continuations" when using those tables. -t From unknown Fri Jun 20 19:54:56 2025 X-Loop: don@donarmstrong.com Subject: bug#192: regexp does not work as documented Reply-To: Stefan Monnier , 192@debbugs.gnu.org Resent-From: Stefan Monnier Resent-To: bug-submit-list@lists.donarmstrong.com Resent-CC: Emacs Bugs Resent-Date: Mon, 12 May 2008 13:50:02 +0000 Resent-Message-ID: Resent-Sender: don@donarmstrong.com X-Emacs-PR-Message: report 192 X-Emacs-PR-Package: emacs X-Emacs-PR-Keywords: Received: via spool by 192-submit@emacsbugs.donarmstrong.com id=B192.121059984024962 (code B ref 192); Mon, 12 May 2008 13:50:02 +0000 X-Spam-Checker-Version: SpamAssassin 3.2.3-bugs.debian.org_2005_01_02 (2007-08-08) on rzlab.ucr.edu X-Spam-Level: X-Spam-Status: No, score=0.4 required=4.0 tests=AWL autolearn=ham version=3.2.3-bugs.debian.org_2005_01_02 Received: (at 192) by emacsbugs.donarmstrong.com; 12 May 2008 13:44:00 +0000 Received: from ironport2-out.teksavvy.com (ironport2-out.pppoe.ca [206.248.154.182]) by rzlab.ucr.edu (8.13.8/8.13.8/Debian-3) with ESMTP id m4CDhuds024956 for <192@emacsbugs.donarmstrong.com>; Mon, 12 May 2008 06:43:57 -0700 X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: AocDAH/mJ0jO+JgrdGdsb2JhbACBU5A7ASeYEg X-IronPort-AV: E=Sophos;i="4.27,473,1204520400"; d="scan'208";a="20407483" Received: from smtp.pppoe.ca (HELO smtp.teksavvy.com) ([65.39.196.238]) by ironport2-out.teksavvy.com with ESMTP; 12 May 2008 09:43:50 -0400 Received: from pastel.home ([206.248.152.43]) by smtp.teksavvy.com (Internet Mail Server v1.0) with ESMTP id SSD44550; Mon, 12 May 2008 09:43:50 -0400 Received: by pastel.home (Postfix, from userid 20848) id D59D37F83; Mon, 12 May 2008 09:43:49 -0400 (EDT) From: Stefan Monnier To: Thomas Lord Cc: Chong Yidong , martin rudalics , David Koppelman , 192@debbugs.gnu.org, Bruno Haible , emacs-devel@gnu.org Message-ID: References: <87k5i8ukq8.fsf@stupidchicken.com> <200805061335.11379.bruno@clisp.org> <48204B3D.6000500@gmx.at> <4826A303.3030002@gmx.at> <87abiwoqzd.fsf@stupidchicken.com> <482750F4.2050102@emf.net> <4827B9B8.30406@emf.net> Date: Mon, 12 May 2008 09:43:49 -0400 In-Reply-To: <4827B9B8.30406@emf.net> (Thomas Lord's message of "Sun, 11 May 2008 20:30:00 -0700") User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/23.0.60 (gnu/linux) MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii > years ago, is to consider *offline* DFA conversion (a la 'lex(1)'). That's what I do in lex.el. > The advantage of offline (batch) conversion is that you can burn a lot > of cycles on DFA minimization and, if your offline converter > terminates, you've got a reliably linear matcher. The disadvantages > for *many* uses of regular expressions in Emacs should be pretty > obvious. For something like font-lock, where the regular expressions > don't change that often, that might be a good approach -- precompile > a minimal DFA and then add support for "regular expression > continuations" when using those tables. I do not intend to replace src/regexp.c with a matcher based on offline DFA conversion. Actually, the need to support backrefs makes it pretty much impossible (tho I'm sure there's a way to adapt an offline DFA so it can be used with backrefs), and most importantly it has too different performance characteristics. More specifically, the compilation step should be made explicit. In any case I think you did answer my question: an offline DFA matcher is fine, the worst case is not that common and can be worked around. This is not that different from the current backtracking matcher. Stefan PS: The original motivation for a DFA-matcher is to extend syntax-tables so they can match match multi-char elements. From unknown Fri Jun 20 19:54:56 2025 X-Loop: don@donarmstrong.com Subject: bug#192: regexp does not work as documented Reply-To: David Koppelman , 192@debbugs.gnu.org Resent-From: David Koppelman Resent-To: bug-submit-list@lists.donarmstrong.com Resent-CC: Emacs Bugs Resent-Date: Mon, 12 May 2008 15:10:03 +0000 Resent-Message-ID: Resent-Sender: don@donarmstrong.com X-Emacs-PR-Message: report 192 X-Emacs-PR-Package: emacs X-Emacs-PR-Keywords: Received: via spool by 192-submit@emacsbugs.donarmstrong.com id=B192.12106046374978 (code B ref 192); Mon, 12 May 2008 15:10:03 +0000 X-Spam-Checker-Version: SpamAssassin 3.2.3-bugs.debian.org_2005_01_02 (2007-08-08) on rzlab.ucr.edu X-Spam-Level: X-Spam-Status: No, score=0.5 required=4.0 tests=AWL,MURPHY_SEX_L2 autolearn=no version=3.2.3-bugs.debian.org_2005_01_02 Received: (at 192) by emacsbugs.donarmstrong.com; 12 May 2008 15:03:57 +0000 Received: from ecelsrv1.ece.lsu.edu (ecelsrv1.ece.lsu.edu [130.39.223.98]) by rzlab.ucr.edu (8.13.8/8.13.8/Debian-3) with ESMTP id m4CF3rK6004972 for <192@emacsbugs.donarmstrong.com>; Mon, 12 May 2008 08:03:54 -0700 Received: from localhost (unknown [127.0.0.1]) by ecelsrv1.ece.lsu.edu (Postfix) with ESMTP id 47536283CA; Mon, 12 May 2008 15:03:53 +0000 (UTC) X-Virus-Scanned: amavisd-new at ece.lsu.edu Received: from ecelsrv1.ece.lsu.edu ([127.0.0.1]) by localhost (ecelsrv1.ece.lsu.edu [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id EhHBp4hL8c4p; Mon, 12 May 2008 10:03:52 -0500 (CDT) Received: from nested.ece.lsu.edu (nested.ece.lsu.edu [130.39.222.143]) by ecelsrv1.ece.lsu.edu (Postfix) with ESMTP id 741F6283C6; Mon, 12 May 2008 10:03:52 -0500 (CDT) From: David Koppelman To: Stefan Monnier Cc: martin rudalics , Chong Yidong , 192@debbugs.gnu.org, Bruno Haible , emacs-devel@gnu.org References: <87k5i8ukq8.fsf@stupidchicken.com> <200805061335.11379.bruno@clisp.org> <48204B3D.6000500@gmx.at> <4826A303.3030002@gmx.at> <87abiwoqzd.fsf@stupidchicken.com> Date: Mon, 12 May 2008 10:03:52 -0500 In-Reply-To: (Stefan Monnier's message of "Sun, 11 May 2008 21:28:18 -0400") Message-ID: User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/23.0.60 (gnu/linux) MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii > I guess I simply do not understand what you propose. Any improvement in > the multiline handling is welcome, but beware: this is not an easy area. I'm proposing that font-lock divide keywords into two or three classes, ordinary, multi-line, and maybe mega-line, matches for multi-line and mega-line keywords would be over much larger regions. Here is how it might work with two classes (keep in mind that I don't yet have a thorough understanding of font-lock and jit-lock): Multi-line keywords are explicitly identified as such, perhaps through keyword syntax or the way they are given to font-lock (say, using font-lock-multiline-keywords). Explicit identification avoids performance problems from keywords that, though technically multi-line, rarely span more than a few lines. Functions such as font-lock-default-fontify-region would find two sets of extended regions, ordinary and multi, running functions on two hooks for this purpose. The multi-line hook might extend the region based on the size of the largest supported match rather than using the multline property. The multiline property might still be useful for non-deferred handling of existing matches. Functions such as font-lock-fontify-keywords-region would be passed both extended regions and use the region appropriate for each keyword they process. The large region is only used on the few multi-line patterns that need it. Here I'm assuming that a mode might have hundreds of single-line (or two-line) keywords and only a few multi-line keywords, and the multi-line keywords might span no more than hundreds of lines. We could guarantee that matches for such patterns are perfect (using a line-count-limit variable). If there were a third class, mega-line, it would have its own text property and region-extension hook. Stefan Monnier writes: >> A better solution would be to have font-lock use multi-line extended >> regions selectively. Perhaps a hint in the current keyword syntax >> (say, explicitly applying the font-lock-multiline property), or a >> separate method for providing multi-line keywords to font-lock. > > I don't understand the difference between the above and the application > of font-lock-multiline properties which you seem to have tried and rejected. > > I don't necessarily disagree with your rejection of font-lock-multiline: > it can have disastrous effect indeed if the multiline region becomes large. > >> Such keywords would get the multi-line extended regions, the other >> just the whole-line extensions (or whatever the hooks do). >> Is this something the font-lock maintainers would consider? > > I guess I simply do not understand what you propose. Any improvement in > the multiline handling is welcome, but beware: this is not an easy area. > From unknown Fri Jun 20 19:54:56 2025 X-Loop: don@donarmstrong.com Subject: bug#192: regexp does not work as documented Reply-To: Thomas Lord , 192@debbugs.gnu.org Resent-From: Thomas Lord Resent-To: bug-submit-list@lists.donarmstrong.com Resent-CC: Emacs Bugs Resent-Date: Mon, 12 May 2008 15:20:02 +0000 Resent-Message-ID: Resent-Sender: don@donarmstrong.com X-Emacs-PR-Message: report 192 X-Emacs-PR-Package: emacs X-Emacs-PR-Keywords: Received: via spool by 192-submit@emacsbugs.donarmstrong.com id=B192.12106051277169 (code B ref 192); Mon, 12 May 2008 15:20:02 +0000 X-Spam-Checker-Version: SpamAssassin 3.2.3-bugs.debian.org_2005_01_02 (2007-08-08) on rzlab.ucr.edu X-Spam-Level: X-Spam-Status: No, score=0.4 required=4.0 tests=AWL,SPF_HELO_PASS autolearn=ham version=3.2.3-bugs.debian.org_2005_01_02 Received: (at 192) by emacsbugs.donarmstrong.com; 12 May 2008 15:12:07 +0000 Received: from mail.42inc.com (mail.42inc.com [205.149.0.25]) by rzlab.ucr.edu (8.13.8/8.13.8/Debian-3) with ESMTP id m4CFC309007163 for <192@emacsbugs.donarmstrong.com>; Mon, 12 May 2008 08:12:05 -0700 X-TFF-CGPSA-Version: 1.5 X-TFF-CGPSA-Filter-42inc: Scanned X-42-Virus-Scanned: by 42 Antivirus -- Found to be clean. Received: from [69.236.114.9] (account lord@emf.net HELO [192.168.1.64]) by mail.42inc.com (CommuniGate Pro SMTP 5.0.13) with ESMTPA id 30343388; Mon, 12 May 2008 08:12:02 -0700 Message-ID: <48286862.6040105@emf.net> Date: Mon, 12 May 2008 08:55:14 -0700 From: Thomas Lord User-Agent: Thunderbird 1.5.0.5 (X11/20060808) MIME-Version: 1.0 To: Stefan Monnier CC: Chong Yidong , 192@debbugs.gnu.org, emacs-devel@gnu.org, martin rudalics , David Koppelman , Bruno Haible References: <87k5i8ukq8.fsf@stupidchicken.com> <200805061335.11379.bruno@clisp.org> <48204B3D.6000500@gmx.at> <4826A303.3030002@gmx.at> <87abiwoqzd.fsf@stupidchicken.com> <482750F4.2050102@emf.net> <4827B9B8.30406@emf.net> In-Reply-To: Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit Stefan Monnier wrote: > That's what I do in lex.el. > > Sounds nice. Last bits of experience report, then: If it isn't so already, it may be easy to make it so that a choice of which DFA is being used, plus a choice of the "current state" can be represented as lisp objects and cheaply copied. That gives the essence of "regular expression continuations". Handy features that shouldn't be difficult to add (if not present): Let programmers specify "labels" for each NFA state and then, for each DFA state, have either a list of all NFA labels that correspond to that DFA state and/or a more general way to "combine" NFA state labels to make the DFA label. You can wind up with many NFA states combined to a single DFA state, of course, so a "combine" function might be important. Include scanning functions to: ~ advance the DFA at most N characters (or until failure) ~ advance the DFA to the next non-nil state label (or failure) In both cases, give a way for lisp programs to get back not only the label (or failure indication) but also the regular expression continuation. Those features are handy so that (for example) lisp programs can hang a suspended regexp continuation on a buffer character as a property, doing incremental "re-lexing" in application-specific ways. The "advance to non-nil label" feature is useful for writing lisp programs that *do not* need back-referencing or sub-exp locations per se. It is a bit more speculative but also consider functions to: ~ advance the state of a DFA based on characters provided in a function call rather than read from a buffer -- e.g., a buffer position should not have to be part of the state of a running DFA. (advance-dfa re-continuation chr) => re-continuation Why that last one? Because then you can probably use the same DFA engine as the heart of a shift-reduce parser and (for languages that admit such things) write an incremental parser. (You'd be using non-buffer-position DFAs to process token ids emitted by the lexer.) You can also use such a feature for things like serial I/O protocols. Incremental parsers open the door to robust "syntax directed editing" which I think could be an exciting direction for IDE features to take. (Years ago, Thomas Reps and Tim Teitelbaum worked on the "Synthesizer Generator" which I recall had features along these lines (their parser guts were probably different from what I suggest). As I (now vaguely) recall there is a book that talks about their Emacs-based implementation.) Bye. Thanks. And good luck! -t From unknown Fri Jun 20 19:54:56 2025 X-Loop: don@donarmstrong.com Subject: bug#192: regexp does not work as documented Reply-To: tomas@tuxteam.de, 192@debbugs.gnu.org Resent-From: tomas@tuxteam.de Resent-To: bug-submit-list@lists.donarmstrong.com Resent-CC: Emacs Bugs Resent-Date: Mon, 12 May 2008 16:30:03 +0000 Resent-Message-ID: Resent-Sender: don@donarmstrong.com X-Emacs-PR-Message: report 192 X-Emacs-PR-Package: emacs X-Emacs-PR-Keywords: Received: via spool by 192-submit@emacsbugs.donarmstrong.com id=B192.121060935417897 (code B ref 192); Mon, 12 May 2008 16:30:03 +0000 X-Spam-Checker-Version: SpamAssassin 3.2.3-bugs.debian.org_2005_01_02 (2007-08-08) on rzlab.ucr.edu X-Spam-Level: X-Spam-Status: No, score=0.2 required=4.0 tests=FVGT_m_MULTI_ODD, MURPHY_WRONG_WORD2 autolearn=no version=3.2.3-bugs.debian.org_2005_01_02 Received: (at 192) by emacsbugs.donarmstrong.com; 12 May 2008 16:22:34 +0000 Received: from www.elogos.de (alextrapp1.equinoxe.de [217.22.192.104]) by rzlab.ucr.edu (8.13.8/8.13.8/Debian-3) with ESMTP id m4CGMUj1017885 for <192@emacsbugs.donarmstrong.com>; Mon, 12 May 2008 09:22:31 -0700 Received: by www.elogos.de (Postfix, from userid 4000) id E54234B635; Mon, 12 May 2008 16:18:43 +0000 (UTC) Date: Mon, 12 May 2008 16:18:43 +0000 To: Thomas Lord Cc: Stefan Monnier , Chong Yidong , 192@debbugs.gnu.org, emacs-devel@gnu.org, martin rudalics , David Koppelman , Bruno Haible Message-ID: <20080512161843.GA15407@www.trapp.net> References: <4826A303.3030002@gmx.at> <87abiwoqzd.fsf@stupidchicken.com> <482750F4.2050102@emf.net> <4827B9B8.30406@emf.net> <48286862.6040105@emf.net> Mime-Version: 1.0 Content-Type: text/plain; charset=utf-8; x-action=pgp-signed Content-Disposition: inline Content-Transfer-Encoding: 8bit In-Reply-To: <48286862.6040105@emf.net> User-Agent: Mutt/1.5.9i From: tomas@tuxteam.de -----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 On Mon, May 12, 2008 at 08:55:14AM -0700, Thomas Lord wrote: [...] > Why that last one? Because then you can probably use the same > DFA engine as the heart of a shift-reduce parser and (for languages > that admit such things) write an incremental parser. (You'd be using > non-buffer-position DFAs to process token ids emitted by the lexer.) > You can also use such a feature for things like serial I/O protocols. ...and cool things could be done with process-filter-function and its cousin after-insert-file-functions (i.e. parse input on-the-fly). Nifty stuff. Regards - -- tomás -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.1 (GNU/Linux) iD8DBQFIKG3jBcgs9XrR2kYRAtv8AJ9uj1wEjjT4bIPNQxYoYY5iPJW8cwCdE87U vsVarzdJhCu143kN7OGWh/Q= =0dcf -----END PGP SIGNATURE----- From unknown Fri Jun 20 19:54:56 2025 X-Loop: don@donarmstrong.com Subject: bug#192: regexp does not work as documented Reply-To: Stefan Monnier , 192@debbugs.gnu.org Resent-From: Stefan Monnier Resent-To: bug-submit-list@lists.donarmstrong.com Resent-CC: Emacs Bugs Resent-Date: Mon, 12 May 2008 16:35:03 +0000 Resent-Message-ID: Resent-Sender: don@donarmstrong.com X-Emacs-PR-Message: report 192 X-Emacs-PR-Package: emacs X-Emacs-PR-Keywords: Received: via spool by 192-submit@emacsbugs.donarmstrong.com id=B192.121060975118641 (code B ref 192); Mon, 12 May 2008 16:35:03 +0000 X-Spam-Checker-Version: SpamAssassin 3.2.3-bugs.debian.org_2005_01_02 (2007-08-08) on rzlab.ucr.edu X-Spam-Level: X-Spam-Status: No, score=0.4 required=4.0 tests=AWL,MURPHY_SEX_L2 autolearn=no version=3.2.3-bugs.debian.org_2005_01_02 Received: (at 192) by emacsbugs.donarmstrong.com; 12 May 2008 16:29:11 +0000 Received: from ironport2-out.teksavvy.com (ironport2-out.pppoe.ca [206.248.154.182]) by rzlab.ucr.edu (8.13.8/8.13.8/Debian-3) with ESMTP id m4CGT7Pe018635 for <192@emacsbugs.donarmstrong.com>; Mon, 12 May 2008 09:29:09 -0700 X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: AocDACoNKEjO+JgrdGdsb2JhbACBU5A7ASeYRA X-IronPort-AV: E=Sophos;i="4.27,474,1204520400"; d="scan'208";a="20421324" Received: from smtp.pppoe.ca (HELO smtp.teksavvy.com) ([65.39.196.238]) by ironport2-out.teksavvy.com with ESMTP; 12 May 2008 12:29:02 -0400 Received: from pastel.home ([206.248.152.43]) by smtp.teksavvy.com (Internet Mail Server v1.0) with ESMTP id SVP40602; Mon, 12 May 2008 12:29:02 -0400 Received: by pastel.home (Postfix, from userid 20848) id D415C801D; Mon, 12 May 2008 12:29:01 -0400 (EDT) From: Stefan Monnier To: David Koppelman Cc: martin rudalics , Chong Yidong , 192@debbugs.gnu.org, Bruno Haible , emacs-devel@gnu.org Message-ID: References: <87k5i8ukq8.fsf@stupidchicken.com> <200805061335.11379.bruno@clisp.org> <48204B3D.6000500@gmx.at> <4826A303.3030002@gmx.at> <87abiwoqzd.fsf@stupidchicken.com> Date: Mon, 12 May 2008 12:29:01 -0400 In-Reply-To: (David Koppelman's message of "Mon, 12 May 2008 10:03:52 -0500") User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/23.0.60 (gnu/linux) MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii > I'm proposing that font-lock divide keywords into two or three > classes, ordinary, multi-line, and maybe mega-line, matches for > multi-line and mega-line keywords would be over much larger > regions. Here is how it might work with two classes (keep in mind that > I don't yet have a thorough understanding of font-lock and jit-lock): I do not understand how you propose to solve the main problem: Let's say you want to fontify a line spanning chars 100..200 and a multiline region spanning 0..400. Before fontifying, you need to unfontify. The region 100..200 can be completely unfontified, but what about 0..99 and 201..400? You can't unfontify them completely since you don't want to refontify them completely either, so you'd need to figure out which part of the fontification comes from the multiline keywords. Also, the order between keywords is important, so unless you force all multiline keywords to go at the very end, you'd also need to remove (on the 0..99 and 201..400 regions) the fontification coming from small keywords that were placed after multiline keywords and reapply it afterwards? Stefan From unknown Fri Jun 20 19:54:56 2025 X-Loop: don@donarmstrong.com Subject: bug#192: regexp does not work as documented Reply-To: David Koppelman , 192@debbugs.gnu.org Resent-From: David Koppelman Resent-To: bug-submit-list@lists.donarmstrong.com Resent-CC: Emacs Bugs Resent-Date: Mon, 12 May 2008 17:10:05 +0000 Resent-Message-ID: Resent-Sender: don@donarmstrong.com X-Emacs-PR-Message: report 192 X-Emacs-PR-Package: emacs X-Emacs-PR-Keywords: Received: via spool by 192-submit@emacsbugs.donarmstrong.com id=B192.121061188723537 (code B ref 192); Mon, 12 May 2008 17:10:05 +0000 X-Spam-Checker-Version: SpamAssassin 3.2.3-bugs.debian.org_2005_01_02 (2007-08-08) on rzlab.ucr.edu X-Spam-Level: X-Spam-Status: No, score=0.4 required=4.0 tests=AWL,MURPHY_SEX_L2 autolearn=no version=3.2.3-bugs.debian.org_2005_01_02 Received: (at 192) by emacsbugs.donarmstrong.com; 12 May 2008 17:04:47 +0000 Received: from ecelsrv1.ece.lsu.edu (ecelsrv1.ece.lsu.edu [130.39.223.98]) by rzlab.ucr.edu (8.13.8/8.13.8/Debian-3) with ESMTP id m4CH4i7b023531 for <192@emacsbugs.donarmstrong.com>; Mon, 12 May 2008 10:04:45 -0700 Received: from localhost (unknown [127.0.0.1]) by ecelsrv1.ece.lsu.edu (Postfix) with ESMTP id D0DDE283C5; Mon, 12 May 2008 17:04:43 +0000 (UTC) X-Virus-Scanned: amavisd-new at ece.lsu.edu Received: from ecelsrv1.ece.lsu.edu ([127.0.0.1]) by localhost (ecelsrv1.ece.lsu.edu [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id AMet342Tmzkl; Mon, 12 May 2008 12:04:43 -0500 (CDT) Received: from nested.ece.lsu.edu (nested.ece.lsu.edu [130.39.222.143]) by ecelsrv1.ece.lsu.edu (Postfix) with ESMTP id 204C7283C0; Mon, 12 May 2008 12:04:43 -0500 (CDT) From: David Koppelman To: Stefan Monnier Cc: martin rudalics , Chong Yidong , 192@debbugs.gnu.org, Bruno Haible , emacs-devel@gnu.org References: <87k5i8ukq8.fsf@stupidchicken.com> <200805061335.11379.bruno@clisp.org> <48204B3D.6000500@gmx.at> <4826A303.3030002@gmx.at> <87abiwoqzd.fsf@stupidchicken.com> Date: Mon, 12 May 2008 12:04:43 -0500 In-Reply-To: (Stefan Monnier's message of "Mon, 12 May 2008 12:29:01 -0400") Message-ID: User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/23.0.60 (gnu/linux) MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii > a multiline region spanning 0..400. Before fontifying, you need > to unfontify. The region 100..200 can be completely unfontified, but Hadn't thought about that. I don't want things to get too elaborate but it would be nice to have guaranteed behavior below some multi-line size and not risk slow behavior. One possibility is to retain the code as it is, except have extend-region-multiline extend to some maximum size (say, 100 lines) with the expectation that the larger region would be used for deferred fontification (I guess jit-lock does that). The only difference with current operation is that the font-lock-multiline property is ignored both ensuring proper matches (when the property is not present but a pattern would match) and avoiding huge sized regions. Now, if we wanted really large multi-line matches we could unfontify the larger region but use a window+margin sized region (accounting for all buffers visiting the file) for the regular patterns and then mark the other parts of the larger region as unfontified. This would force re-applying the multi-line patterns on buffer motion, though we could cache the match data to avoid re-seaching. Stefan Monnier writes: >> I'm proposing that font-lock divide keywords into two or three >> classes, ordinary, multi-line, and maybe mega-line, matches for >> multi-line and mega-line keywords would be over much larger >> regions. Here is how it might work with two classes (keep in mind that >> I don't yet have a thorough understanding of font-lock and jit-lock): > > I do not understand how you propose to solve the main problem: > Let's say you want to fontify a line spanning chars 100..200 and > a multiline region spanning 0..400. Before fontifying, you need > to unfontify. The region 100..200 can be completely unfontified, but > what about 0..99 and 201..400? You can't unfontify them completely > since you don't want to refontify them completely either, so you'd need > to figure out which part of the fontification comes from the > multiline keywords. > > Also, the order between keywords is important, so unless you force all > multiline keywords to go at the very end, you'd also need to remove (on > the 0..99 and 201..400 regions) the fontification coming from small > keywords that were placed after multiline keywords and reapply > it afterwards? > > > Stefan From debbugs-submit-bounces@debbugs.gnu.org Mon Dec 28 23:06:58 2015 Received: (at control) by debbugs.gnu.org; 29 Dec 2015 04:06:58 +0000 Received: from localhost ([127.0.0.1]:47165 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84) (envelope-from ) id 1aDlYn-0008MP-TZ for submit@debbugs.gnu.org; Mon, 28 Dec 2015 23:06:58 -0500 Received: from mail-qg0-f54.google.com ([209.85.192.54]:36357) by debbugs.gnu.org with esmtp (Exim 4.84) (envelope-from ) id 1aDiKD-0000y0-Rt for control@debbugs.gnu.org; Mon, 28 Dec 2015 19:39:42 -0500 Received: by mail-qg0-f54.google.com with SMTP id e32so65466143qgf.3 for ; Mon, 28 Dec 2015 16:39:41 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=date:message-id:to:from:subject; bh=lpdOKojwJTujxK7hTWp1kYAErgiVVQeKjKHtRd/W6ms=; b=BwCJKxPmcAPkYSrh8/0u5pGpSd+kAphfTTRDllOLEQp6dtYkFH/PJtOt7FDvqFc2kZ 2iRhGdEizrxjULuaPzfIPf9EuVsHn9Z/cmjfWBfG79VcxWJEsLzwZxnIeVzz3Ow8nedc XkCquc7ZyWaB8vgKaedsfe41DXwAk/J7D1V7lYv9Z8PpUiNsCx3RApMRTI60rhd7cM4w yaX2nk/Oj/mZSCsmH1QQeUWQueXQvE6MFYyzmqxMvx/EXfA7Pm4F7ZKDiq5BPBW6BQP2 95karAng5euiqwmELvRDywL0Hp/Jo8Y8oF0/oc98YOCiKHWFBQOQRA1DK618twyuUFxP LGSA== X-Received: by 10.140.171.9 with SMTP id r9mr79712751qhr.93.1451349576216; Mon, 28 Dec 2015 16:39:36 -0800 (PST) Received: from Andrews-MacBook-Pro.local.ahyatt-laptop (cpe-74-73-128-199.nyc.res.rr.com. [74.73.128.199]) by smtp.gmail.com with ESMTPSA id f7sm28052502qhf.7.2015.12.28.16.39.35 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 28 Dec 2015 16:39:35 -0800 (PST) Date: Mon, 28 Dec 2015 19:39:33 -0500 Message-Id: To: control@debbugs.gnu.org From: Andrew Hyatt Subject: control message for bug #192 X-Spam-Score: -0.7 (/) X-Debbugs-Envelope-To: control X-Mailman-Approved-At: Mon, 28 Dec 2015 23:06:57 -0500 X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -0.7 (/) tags 192 unreproducible close 192 From unknown Fri Jun 20 19:54:56 2025 X-Loop: help-debbugs@gnu.org Subject: bug#192: regexp does not work as documented References: <200805060330.45156.bruno@clisp.org> In-Reply-To: <200805060330.45156.bruno@clisp.org> Resent-From: Bruno Haible Original-Sender: "Debbugs-submit" Resent-CC: bug-gnu-emacs@gnu.org Resent-Date: Tue, 29 Dec 2015 17:49:01 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 192 X-GNU-PR-Package: emacs X-GNU-PR-Keywords: unreproducible To: 192@debbugs.gnu.org Received: via spool by 192-submit@debbugs.gnu.org id=B192.145141133215198 (code B ref 192); Tue, 29 Dec 2015 17:49:01 +0000 Received: (at 192) by debbugs.gnu.org; 29 Dec 2015 17:48:52 +0000 Received: from localhost ([127.0.0.1]:48878 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84) (envelope-from ) id 1aDyOC-0003x3-1y for submit@debbugs.gnu.org; Tue, 29 Dec 2015 12:48:52 -0500 Received: from mo4-p00-ob.smtp.rzone.de ([81.169.146.216]:57739) by debbugs.gnu.org with esmtp (Exim 4.84) (envelope-from ) id 1aDyOA-0003wv-JO for 192@debbugs.gnu.org; Tue, 29 Dec 2015 12:48:51 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; t=1451411328; l=104; s=domk; d=clisp.org; h=Content-Type:Content-Transfer-Encoding:MIME-Version:Date:Subject:To: From; bh=dkkPVH/LLj/3hgPeaw38EYwYyOvr62KjJ0A5leY6jMc=; b=tKoeyr40xHIAXRBtLkYzW3+pclwsLZ6nWJyf4dpNwsJsmO8YHc4/8EvcXjBf1+hY3Wi kfBw5nkxnq93ZUF5YrBOj6E+qmO++sgA2qlHQpcPPIIGR2+pmFmlBwN9+IFTrw2vKAx1V QUMah7catUbJmw2gC/6ssNVFQ3kggQgHHCU= X-RZG-AUTH: :Ln4Re0+Ic/6oZXR1YgKryK8brksyK8dozXDwHXjf9hj/zDNRb/Q441VPjQ== X-RZG-CLASS-ID: mo00 Received: from bruno.haible.de (dslb-088-068-062-172.088.068.pools.vodafone-ip.de [88.68.62.172]) by smtp.strato.de (RZmta 37.15 DYNA|AUTH) with ESMTPSA id j072b0rBTHmmb3L (using TLSv1 with cipher ECDHE-RSA-AES256-SHA (curve secp521r1 with 521 ECDH bits, eq. 15360 bits RSA)) (Client did not present a certificate); Tue, 29 Dec 2015 18:48:48 +0100 (CET) From: Bruno Haible Date: Tue, 29 Dec 2015 18:48:48 +0100 Message-ID: <3319321.yMrkOOPrlO@linuix.haible.de> User-Agent: KMail/4.8.5 (Linux/3.8.0-44-generic; KDE/4.8.5; x86_64; ; ) MIME-Version: 1.0 Content-Transfer-Encoding: 7Bit Content-Type: text/plain; charset="us-ascii" X-Spam-Score: -0.7 (/) X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -0.7 (/) The bug was reproducible with emacs 22.2.1. I now verified that it is fixed in emacs 23.1. Thanks!