From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.io!.POSTED.blaine.gmane.org!not-for-mail From: Eric Abrahamsen Newsgroups: gmane.emacs.devel Subject: Re: Make peg.el a built-in library? Date: Sat, 09 Oct 2021 09:47:44 -0700 Message-ID: <874k9qxhzj.fsf@ericabrahamsen.net> References: <875yvtbbn3.fsf@ericabrahamsen.net> <87a6jjc7c8.fsf@web.de> Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="=-=-=" Injection-Info: ciao.gmane.io; posting-host="blaine.gmane.org:116.202.254.214"; logging-data="9262"; mail-complaints-to="usenet@ciao.gmane.io" User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/29.0.50 (gnu/linux) Cc: Michael Heerdegen To: emacs-devel@gnu.org Cancel-Lock: sha1:f4JX087sEFgiMzI2ZOtvYqOv22Q= Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane-mx.org@gnu.org Sat Oct 09 18:49:13 2021 Return-path: Envelope-to: ged-emacs-devel@m.gmane-mx.org Original-Received: from lists.gnu.org ([209.51.188.17]) by ciao.gmane.io with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1mZFX6-0002Dm-Sx for ged-emacs-devel@m.gmane-mx.org; Sat, 09 Oct 2021 18:49:12 +0200 Original-Received: from localhost ([::1]:43268 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1mZFX5-0007ys-7q for ged-emacs-devel@m.gmane-mx.org; Sat, 09 Oct 2021 12:49:11 -0400 Original-Received: from eggs.gnu.org ([2001:470:142:3::10]:33608) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1mZFVs-0006rh-2s for emacs-devel@gnu.org; Sat, 09 Oct 2021 12:47:56 -0400 Original-Received: from ciao.gmane.io ([116.202.254.214]:46156) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1mZFVp-00017P-TR for emacs-devel@gnu.org; Sat, 09 Oct 2021 12:47:55 -0400 Original-Received: from list by ciao.gmane.io with local (Exim 4.92) (envelope-from ) id 1mZFVn-0000V8-Mb for emacs-devel@gnu.org; Sat, 09 Oct 2021 18:47:51 +0200 X-Injected-Via-Gmane: http://gmane.org/ Received-SPF: pass client-ip=116.202.254.214; envelope-from=ged-emacs-devel@m.gmane-mx.org; helo=ciao.gmane.io X-Spam_score_int: -16 X-Spam_score: -1.7 X-Spam_bar: - X-Spam_report: (-1.7 / 5.0 requ) BAYES_00=-1.9, HEADER_FROM_DIFFERENT_DOMAINS=0.249, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=no autolearn_force=no X-Spam_action: no action X-BeenThere: emacs-devel@gnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: "Emacs development discussions." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: emacs-devel-bounces+ged-emacs-devel=m.gmane-mx.org@gnu.org Original-Sender: "Emacs-devel" Xref: news.gmane.io gmane.emacs.devel:276619 Archived-At: --=-=-= Content-Type: text/plain Stefan Monnier writes: >> (1) Can we improve the introduction in the file header a bit? I would >> add a link to the wikipedia page: >> >> https://en.wikipedia.org/wiki/Parsing_expression_grammar >> >> it explains some background. > > I can't speak for Helmut, but I think you should feel free to make such > a change, yes. I've still got this documentation patch I haven't applied, I can just add that link to this patch? --=-=-= Content-Type: text/x-patch Content-Disposition: attachment; filename=peg-doc-patch.diff diff --git a/peg.el b/peg.el index d71c707dc0..0e4221eeb7 100644 --- a/peg.el +++ b/peg.el @@ -79,17 +79,69 @@ ;; Beginning-of-Symbol (bos) ;; End-of-Symbol (eos) ;; -;; PEXs also support parsing actions, i.e. Lisp snippets which -;; are executed when a pex matches. This can be used to construct -;; syntax trees or for similar tasks. Actions are written as +;; Rules can refer to other rules, and a grammar is often structured +;; as a tree, with a root rule referring to one or more "branch +;; rules", all the way down to the "leaf rules" that deal with actual +;; buffer text. Rules can be recursive or mutually referential, +;; though care must be taken not to create infinite loops. +;; +;; PEXs also support parsing actions, i.e. Lisp snippets which are +;; executed when a pex matches. This can be used to construct syntax +;; trees or for similar tasks. The most basic form of action is +;; written as: ;; ;; (action FORM) ; evaluate FORM for its side-effects -;; `(VAR... -- FORM...) ; stack action ;; ;; Actions don't consume input, but are executed at the point of -;; match. A "stack action" takes VARs from the "value stack" and -;; pushes the result of evaluating FORMs to that stack. -;; See `peg-ex-parse-int' in `peg-tests.el' for an example. +;; match. Another kind of action is called a "stack action", and +;; looks like this: +;; +;; `(VAR... -- FORM...) ; stack action +;; +;; A stack action takes VARs from the "value stack" and pushes the +;; results of evaluating FORMs to that stack. + +;; The value stack is created during the course of parsing. Certain +;; operators (see below) that match buffer text can push values onto +;; this stack. "Upstream" rules can then draw values from the stack, +;; and optionally push new ones back. For instance, consider this +;; very simple grammar: +;; +;; (with-peg-rules +;; ((query (+ term) (eol)) +;; (term key ":" value (opt (+ [space])) +;; `(k v -- (cons (intern k) v))) +;; (key (substring (and (not ":") (+ [word])))) +;; (value (or string-value number-value)) +;; (string-value (substring (+ [alpha]))) +;; (number-value (substring (+ [digit])) +;; `(val -- (string-to-number val)))) +;; (peg-run (peg query))) +;; +;; This invocation of `peg-run' would parse this buffer text: +;; +;; name:Jane age:30 +;; +;; And return this Elisp sexp: +;; +;; ((age . 30) (name . "Jane")) +;; +;; Note that, in complex grammars, some care must be taken to make +;; sure that the number and type of values drawn from the stack always +;; match those pushed. In the example above, both `string-value' and +;; `number-value' push a single value to the stack. Since the `value' +;; rule only includes these two sub-rules, any upstream rule that +;; makes use of `value' can be confident it will always and only push +;; a single value to the stack. +;; +;; Stack action forms are in a sense analogous to lambda forms: the +;; symbols before the "--" are the equivalent of lambda arguments, +;; while the forms after the "--" are return values. The difference +;; being that a lambda form can only return a single value, while a +;; stack action can push multiple values onto the stack. It's also +;; perfectly valid to use `(-- FORM...)' or `(VAR... --)': the former +;; pushes values to the stack without consuming any, and the latter +;; pops values from the stack and discards them. ;; ;; Derived Operators: ;; @@ -101,6 +153,8 @@ ;; (replace E RPL); Match E and replace the matched region with RPL. ;; (list E) ; Match E and push a list of the items that E produced. ;; +;; See `peg-ex-parse-int' in `peg-tests.el' for further examples. +;; ;; Regexp equivalents: ;; ;; Here a some examples for regexps and how those could be written as pex. @@ -177,7 +231,7 @@ EXPS is a list of rules/expressions that failed.") ;;;; Main entry points -;; Sometimes (with-peg-rule ... (peg-run (peg ...))) is too +;; Sometimes (with-peg-rules ... (peg-run (peg ...))) is too ;; longwinded for the task at hand, so `peg-parse' comes in handy. (defmacro peg-parse (&rest pexs) "Match PEXS at point. --=-=-=--