Mercurial > emacs
annotate lisp/emacs-lisp/smie.el @ 111840:b050075901af
shr.el (shr-find-fill-point): Don't break a line after a kinsoku-bol character if a non-breakable character follows.
author | Katsumi Yamaoka <yamaoka@jpl.org> |
---|---|
date | Tue, 07 Dec 2010 01:21:09 +0000 |
parents | 141d3f14d8c3 |
children | 417b1e4d63cd |
rev | line source |
---|---|
111382
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1 ;;; smie.el --- Simple Minded Indentation Engine |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2 |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
3 ;; Copyright (C) 2010 Free Software Foundation, Inc. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
4 |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
5 ;; Author: Stefan Monnier <monnier@iro.umontreal.ca> |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
6 ;; Keywords: languages, lisp, internal, parsing, indentation |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
7 |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
8 ;; This file is part of GNU Emacs. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
9 |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
10 ;; GNU Emacs is free software; you can redistribute it and/or modify |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
11 ;; it under the terms of the GNU General Public License as published by |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
12 ;; the Free Software Foundation, either version 3 of the License, or |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
13 ;; (at your option) any later version. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
14 |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
15 ;; GNU Emacs is distributed in the hope that it will be useful, |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
16 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
17 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
18 ;; GNU General Public License for more details. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
19 |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
20 ;; You should have received a copy of the GNU General Public License |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
21 ;; along with this program. If not, see <http://www.gnu.org/licenses/>. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
22 |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
23 ;;; Commentary: |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
24 |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
25 ;; While working on the SML indentation code, the idea grew that maybe |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
26 ;; I could write something generic to do the same thing, and at the |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
27 ;; end of working on the SML code, I had a pretty good idea of what it |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
28 ;; could look like. That idea grew stronger after working on |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
29 ;; LaTeX indentation. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
30 ;; |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
31 ;; So at some point I decided to try it out, by writing a new |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
32 ;; indentation code for Coq while trying to keep most of the code |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
33 ;; "table driven", where only the tables are Coq-specific. The result |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
34 ;; (which was used for Beluga-mode as well) turned out to be based on |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
35 ;; something pretty close to an operator precedence parser. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
36 |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
37 ;; So here is another rewrite, this time following the actual principles of |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
38 ;; operator precedence grammars. Why OPG? Even though they're among the |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
39 ;; weakest kinds of parsers, these parsers have some very desirable properties |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
40 ;; for Emacs: |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
41 ;; - most importantly for indentation, they work equally well in either |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
42 ;; direction, so you can use them to parse backward from the indentation |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
43 ;; point to learn the syntactic context; |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
44 ;; - they work locally, so there's no need to keep a cache of |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
45 ;; the parser's state; |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
46 ;; - because of that locality, indentation also works just fine when earlier |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
47 ;; parts of the buffer are syntactically incorrect since the indentation |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
48 ;; looks at "as little as possible" of the buffer to make an indentation |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
49 ;; decision. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
50 ;; - they typically have no error handling and can't even detect a parsing |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
51 ;; error, so we don't have to worry about what to do in case of a syntax |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
52 ;; error because the parser just automatically does something. Better yet, |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
53 ;; we can afford to use a sloppy grammar. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
54 |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
55 ;; A good background to understand the development (especially the parts |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
56 ;; building the 2D precedence tables and then computing the precedence levels |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
57 ;; from it) can be found in pages 187-194 of "Parsing techniques" by Dick Grune |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
58 ;; and Ceriel Jacobs (BookBody.pdf available at |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
59 ;; http://www.cs.vu.nl/~dick/PTAPG.html). |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
60 ;; |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
61 ;; OTOH we had to kill many chickens, read many coffee grounds, and practice |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
62 ;; untold numbers of black magic spells, to come up with the indentation code. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
63 ;; Since then, some of that code has been beaten into submission, but the |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
64 ;; smie-indent-keyword is still pretty obscure. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
65 |
111603
c901fac3b428
* lisp/emacs-lisp/smie.el (smie-rule-parent, smie-indent--rule):
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111382
diff
changeset
|
66 ;; Conflict resolution: |
c901fac3b428
* lisp/emacs-lisp/smie.el (smie-rule-parent, smie-indent--rule):
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111382
diff
changeset
|
67 ;; |
c901fac3b428
* lisp/emacs-lisp/smie.el (smie-rule-parent, smie-indent--rule):
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111382
diff
changeset
|
68 ;; - One source of conflicts is when you have: |
c901fac3b428
* lisp/emacs-lisp/smie.el (smie-rule-parent, smie-indent--rule):
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111382
diff
changeset
|
69 ;; (exp ("IF" exp "ELSE" exp "END") ("CASE" cases "END")) |
c901fac3b428
* lisp/emacs-lisp/smie.el (smie-rule-parent, smie-indent--rule):
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111382
diff
changeset
|
70 ;; (cases (cases "ELSE" insts) ...) |
c901fac3b428
* lisp/emacs-lisp/smie.el (smie-rule-parent, smie-indent--rule):
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111382
diff
changeset
|
71 ;; The IF-rule implies ELSE=END and the CASE-rule implies ELSE>END. |
c901fac3b428
* lisp/emacs-lisp/smie.el (smie-rule-parent, smie-indent--rule):
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111382
diff
changeset
|
72 ;; FIXME: we could try to resolve such conflicts automatically by changing |
c901fac3b428
* lisp/emacs-lisp/smie.el (smie-rule-parent, smie-indent--rule):
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111382
diff
changeset
|
73 ;; the way BNF rules such as the IF-rule is handled. I.e. rather than |
c901fac3b428
* lisp/emacs-lisp/smie.el (smie-rule-parent, smie-indent--rule):
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111382
diff
changeset
|
74 ;; IF=ELSE and ELSE=END, we could turn them into IF<ELSE and ELSE>END |
c901fac3b428
* lisp/emacs-lisp/smie.el (smie-rule-parent, smie-indent--rule):
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111382
diff
changeset
|
75 ;; and IF=END, |
c901fac3b428
* lisp/emacs-lisp/smie.el (smie-rule-parent, smie-indent--rule):
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111382
diff
changeset
|
76 |
111605
ca8b605ca70f
* lisp/emacs-lisp/smie.el (smie-prec2->grammar): Obey equality constraints
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111603
diff
changeset
|
77 ;; TODO & BUGS: |
ca8b605ca70f
* lisp/emacs-lisp/smie.el (smie-prec2->grammar): Obey equality constraints
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111603
diff
changeset
|
78 ;; |
ca8b605ca70f
* lisp/emacs-lisp/smie.el (smie-prec2->grammar): Obey equality constraints
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111603
diff
changeset
|
79 ;; - Using the structural information SMIE gives us, it should be possible to |
ca8b605ca70f
* lisp/emacs-lisp/smie.el (smie-prec2->grammar): Obey equality constraints
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111603
diff
changeset
|
80 ;; implement a `smie-align' command that would automatically figure out what |
ca8b605ca70f
* lisp/emacs-lisp/smie.el (smie-prec2->grammar): Obey equality constraints
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111603
diff
changeset
|
81 ;; there is to align and how to do it (something like: align the token of |
ca8b605ca70f
* lisp/emacs-lisp/smie.el (smie-prec2->grammar): Obey equality constraints
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111603
diff
changeset
|
82 ;; lowest precedence that appears the same number of times on all lines, |
ca8b605ca70f
* lisp/emacs-lisp/smie.el (smie-prec2->grammar): Obey equality constraints
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111603
diff
changeset
|
83 ;; and then do the same on each side of that token). |
ca8b605ca70f
* lisp/emacs-lisp/smie.el (smie-prec2->grammar): Obey equality constraints
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111603
diff
changeset
|
84 ;; - Maybe accept two juxtaposed non-terminals in the BNF under the condition |
ca8b605ca70f
* lisp/emacs-lisp/smie.el (smie-prec2->grammar): Obey equality constraints
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111603
diff
changeset
|
85 ;; that the first always ends with a terminal, or that the second always |
ca8b605ca70f
* lisp/emacs-lisp/smie.el (smie-prec2->grammar): Obey equality constraints
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111603
diff
changeset
|
86 ;; starts with a terminal. |
111382
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
87 |
111605
ca8b605ca70f
* lisp/emacs-lisp/smie.el (smie-prec2->grammar): Obey equality constraints
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111603
diff
changeset
|
88 ;;; Code: |
111382
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
89 |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
90 (eval-when-compile (require 'cl)) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
91 |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
92 (defgroup smie nil |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
93 "Simple Minded Indentation Engine." |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
94 :group 'languages) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
95 |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
96 (defvar comment-continue) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
97 (declare-function comment-string-strip "newcomment" (str beforep afterp)) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
98 |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
99 ;;; Building precedence level tables from BNF specs. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
100 |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
101 ;; We have 4 different representations of a "grammar": |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
102 ;; - a BNF table, which is a list of BNF rules of the form |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
103 ;; (NONTERM RHS1 ... RHSn) where each RHS is a list of terminals (tokens) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
104 ;; or nonterminals. Any element in these lists which does not appear as |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
105 ;; the `car' of a BNF rule is taken to be a terminal. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
106 ;; - A list of precedences (key word "precs"), is a list, sorted |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
107 ;; from lowest to highest precedence, of precedence classes that |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
108 ;; have the form (ASSOCIATIVITY TERMINAL1 .. TERMINALn), where |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
109 ;; ASSOCIATIVITY can be `assoc', `left', `right' or `nonassoc'. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
110 ;; - a 2 dimensional precedence table (key word "prec2"), is a 2D |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
111 ;; table recording the precedence relation (can be `<', `=', `>', or |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
112 ;; nil) between each pair of tokens. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
113 ;; - a precedence-level table (key word "grammar"), which is a alist |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
114 ;; giving for each token its left and right precedence level (a |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
115 ;; number or nil). This is used in `smie-grammar'. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
116 ;; The prec2 tables are only intermediate data structures: the source |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
117 ;; code normally provides a mix of BNF and precs tables, and then |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
118 ;; turns them into a levels table, which is what's used by the rest of |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
119 ;; the SMIE code. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
120 |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
121 (defun smie-set-prec2tab (table x y val &optional override) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
122 (assert (and x y)) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
123 (let* ((key (cons x y)) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
124 (old (gethash key table))) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
125 (if (and old (not (eq old val))) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
126 (if (and override (gethash key override)) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
127 ;; FIXME: The override is meant to resolve ambiguities, |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
128 ;; but it also hides real conflicts. It would be great to |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
129 ;; be able to distinguish the two cases so that overrides |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
130 ;; don't hide real conflicts. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
131 (puthash key (gethash key override) table) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
132 (display-warning 'smie (format "Conflict: %s %s/%s %s" x old val y))) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
133 (puthash key val table)))) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
134 |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
135 (put 'smie-precs->prec2 'pure t) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
136 (defun smie-precs->prec2 (precs) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
137 "Compute a 2D precedence table from a list of precedences. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
138 PRECS should be a list, sorted by precedence (e.g. \"+\" will |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
139 come before \"*\"), of elements of the form \(left OP ...) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
140 or (right OP ...) or (nonassoc OP ...) or (assoc OP ...). All operators in |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
141 one of those elements share the same precedence level and associativity." |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
142 (let ((prec2-table (make-hash-table :test 'equal))) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
143 (dolist (prec precs) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
144 (dolist (op (cdr prec)) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
145 (let ((selfrule (cdr (assq (car prec) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
146 '((left . >) (right . <) (assoc . =)))))) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
147 (when selfrule |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
148 (dolist (other-op (cdr prec)) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
149 (smie-set-prec2tab prec2-table op other-op selfrule)))) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
150 (let ((op1 '<) (op2 '>)) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
151 (dolist (other-prec precs) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
152 (if (eq prec other-prec) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
153 (setq op1 '> op2 '<) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
154 (dolist (other-op (cdr other-prec)) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
155 (smie-set-prec2tab prec2-table op other-op op2) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
156 (smie-set-prec2tab prec2-table other-op op op1))))))) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
157 prec2-table)) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
158 |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
159 (put 'smie-merge-prec2s 'pure t) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
160 (defun smie-merge-prec2s (&rest tables) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
161 (if (null (cdr tables)) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
162 (car tables) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
163 (let ((prec2 (make-hash-table :test 'equal))) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
164 (dolist (table tables) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
165 (maphash (lambda (k v) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
166 (if (consp k) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
167 (smie-set-prec2tab prec2 (car k) (cdr k) v) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
168 (if (and (gethash k prec2) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
169 (not (equal (gethash k prec2) v))) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
170 (error "Conflicting values for %s property" k) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
171 (puthash k v prec2)))) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
172 table)) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
173 prec2))) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
174 |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
175 (put 'smie-bnf->prec2 'pure t) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
176 (defun smie-bnf->prec2 (bnf &rest precs) |
111603
c901fac3b428
* lisp/emacs-lisp/smie.el (smie-rule-parent, smie-indent--rule):
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111382
diff
changeset
|
177 ;; FIXME: Add repetition operator like (repeat <separator> <elems>). |
c901fac3b428
* lisp/emacs-lisp/smie.el (smie-rule-parent, smie-indent--rule):
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111382
diff
changeset
|
178 ;; Maybe also add (or <elem1> <elem2>...) for things like |
c901fac3b428
* lisp/emacs-lisp/smie.el (smie-rule-parent, smie-indent--rule):
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111382
diff
changeset
|
179 ;; (exp (exp (or "+" "*" "=" ..) exp)). |
c901fac3b428
* lisp/emacs-lisp/smie.el (smie-rule-parent, smie-indent--rule):
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111382
diff
changeset
|
180 ;; Basically, make it EBNF (except for the specification of a separator in |
c901fac3b428
* lisp/emacs-lisp/smie.el (smie-rule-parent, smie-indent--rule):
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111382
diff
changeset
|
181 ;; the repetition). |
111382
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
182 (let ((nts (mapcar 'car bnf)) ;Non-terminals |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
183 (first-ops-table ()) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
184 (last-ops-table ()) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
185 (first-nts-table ()) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
186 (last-nts-table ()) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
187 (prec2 (make-hash-table :test 'equal)) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
188 (override (apply 'smie-merge-prec2s |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
189 (mapcar 'smie-precs->prec2 precs))) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
190 again) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
191 (dolist (rules bnf) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
192 (let ((nt (car rules)) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
193 (last-ops ()) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
194 (first-ops ()) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
195 (last-nts ()) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
196 (first-nts ())) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
197 (dolist (rhs (cdr rules)) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
198 (unless (consp rhs) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
199 (signal 'wrong-type-argument `(consp ,rhs))) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
200 (if (not (member (car rhs) nts)) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
201 (pushnew (car rhs) first-ops) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
202 (pushnew (car rhs) first-nts) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
203 (when (consp (cdr rhs)) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
204 ;; If the first is not an OP we add the second (which |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
205 ;; should be an OP if BNF is an "operator grammar"). |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
206 ;; Strictly speaking, this should only be done if the |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
207 ;; first is a non-terminal which can expand to a phrase |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
208 ;; without any OP in it, but checking doesn't seem worth |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
209 ;; the trouble, and it lets the writer of the BNF |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
210 ;; be a bit more sloppy by skipping uninteresting base |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
211 ;; cases which are terminals but not OPs. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
212 (assert (not (member (cadr rhs) nts))) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
213 (pushnew (cadr rhs) first-ops))) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
214 (let ((shr (reverse rhs))) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
215 (if (not (member (car shr) nts)) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
216 (pushnew (car shr) last-ops) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
217 (pushnew (car shr) last-nts) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
218 (when (consp (cdr shr)) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
219 (assert (not (member (cadr shr) nts))) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
220 (pushnew (cadr shr) last-ops))))) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
221 (push (cons nt first-ops) first-ops-table) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
222 (push (cons nt last-ops) last-ops-table) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
223 (push (cons nt first-nts) first-nts-table) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
224 (push (cons nt last-nts) last-nts-table))) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
225 ;; Compute all first-ops by propagating the initial ones we have |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
226 ;; now, according to first-nts. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
227 (setq again t) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
228 (while (prog1 again (setq again nil)) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
229 (dolist (first-nts first-nts-table) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
230 (let* ((nt (pop first-nts)) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
231 (first-ops (assoc nt first-ops-table))) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
232 (dolist (first-nt first-nts) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
233 (dolist (op (cdr (assoc first-nt first-ops-table))) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
234 (unless (member op first-ops) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
235 (setq again t) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
236 (push op (cdr first-ops)))))))) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
237 ;; Same thing for last-ops. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
238 (setq again t) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
239 (while (prog1 again (setq again nil)) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
240 (dolist (last-nts last-nts-table) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
241 (let* ((nt (pop last-nts)) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
242 (last-ops (assoc nt last-ops-table))) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
243 (dolist (last-nt last-nts) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
244 (dolist (op (cdr (assoc last-nt last-ops-table))) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
245 (unless (member op last-ops) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
246 (setq again t) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
247 (push op (cdr last-ops)))))))) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
248 ;; Now generate the 2D precedence table. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
249 (dolist (rules bnf) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
250 (dolist (rhs (cdr rules)) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
251 (while (cdr rhs) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
252 (cond |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
253 ((member (car rhs) nts) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
254 (dolist (last (cdr (assoc (car rhs) last-ops-table))) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
255 (smie-set-prec2tab prec2 last (cadr rhs) '> override))) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
256 ((member (cadr rhs) nts) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
257 (dolist (first (cdr (assoc (cadr rhs) first-ops-table))) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
258 (smie-set-prec2tab prec2 (car rhs) first '< override)) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
259 (if (and (cddr rhs) (not (member (car (cddr rhs)) nts))) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
260 (smie-set-prec2tab prec2 (car rhs) (car (cddr rhs)) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
261 '= override))) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
262 (t (smie-set-prec2tab prec2 (car rhs) (cadr rhs) '= override))) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
263 (setq rhs (cdr rhs))))) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
264 ;; Keep track of which tokens are openers/closer, so they can get a nil |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
265 ;; precedence in smie-prec2->grammar. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
266 (puthash :smie-open/close-alist (smie-bnf-classify bnf) prec2) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
267 (puthash :smie-closer-alist (smie-bnf-closer-alist bnf) prec2) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
268 prec2)) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
269 |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
270 ;; (defun smie-prec2-closer-alist (prec2 include-inners) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
271 ;; "Build a closer-alist from a PREC2 table. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
272 ;; The return value is in the same form as `smie-closer-alist'. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
273 ;; INCLUDE-INNERS if non-nil means that inner keywords will be included |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
274 ;; in the table, e.g. the table will include things like (\"if\" . \"else\")." |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
275 ;; (let* ((non-openers '()) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
276 ;; (non-closers '()) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
277 ;; ;; For each keyword, this gives the matching openers, if any. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
278 ;; (openers (make-hash-table :test 'equal)) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
279 ;; (closers '()) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
280 ;; (done nil)) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
281 ;; ;; First, find the non-openers and non-closers. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
282 ;; (maphash (lambda (k v) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
283 ;; (unless (or (eq v '<) (member (cdr k) non-openers)) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
284 ;; (push (cdr k) non-openers)) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
285 ;; (unless (or (eq v '>) (member (car k) non-closers)) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
286 ;; (push (car k) non-closers))) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
287 ;; prec2) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
288 ;; ;; Then find the openers and closers. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
289 ;; (maphash (lambda (k _) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
290 ;; (unless (member (car k) non-openers) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
291 ;; (puthash (car k) (list (car k)) openers)) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
292 ;; (unless (or (member (cdr k) non-closers) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
293 ;; (member (cdr k) closers)) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
294 ;; (push (cdr k) closers))) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
295 ;; prec2) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
296 ;; ;; Then collect the matching elements. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
297 ;; (while (not done) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
298 ;; (setq done t) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
299 ;; (maphash (lambda (k v) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
300 ;; (when (eq v '=) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
301 ;; (let ((aopeners (gethash (car k) openers)) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
302 ;; (dopeners (gethash (cdr k) openers)) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
303 ;; (new nil)) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
304 ;; (dolist (o aopeners) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
305 ;; (unless (member o dopeners) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
306 ;; (setq new t) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
307 ;; (push o dopeners))) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
308 ;; (when new |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
309 ;; (setq done nil) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
310 ;; (puthash (cdr k) dopeners openers))))) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
311 ;; prec2)) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
312 ;; ;; Finally, dump the resulting table. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
313 ;; (let ((alist '())) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
314 ;; (maphash (lambda (k v) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
315 ;; (when (or include-inners (member k closers)) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
316 ;; (dolist (opener v) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
317 ;; (unless (equal opener k) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
318 ;; (push (cons opener k) alist))))) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
319 ;; openers) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
320 ;; alist))) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
321 |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
322 (defun smie-bnf-closer-alist (bnf &optional no-inners) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
323 ;; We can also build this closer-alist table from a prec2 table, |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
324 ;; but it takes more work, and the order is unpredictable, which |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
325 ;; is a problem for smie-close-block. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
326 ;; More convenient would be to build it from a levels table since we |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
327 ;; always have this table (contrary to the BNF), but it has all the |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
328 ;; disadvantages of the prec2 case plus the disadvantage that the levels |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
329 ;; table has lost some info which would result in extra invalid pairs. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
330 "Build a closer-alist from a BNF table. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
331 The return value is in the same form as `smie-closer-alist'. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
332 NO-INNERS if non-nil means that inner keywords will be excluded |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
333 from the table, e.g. the table will not include things like (\"if\" . \"else\")." |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
334 (let ((nts (mapcar #'car bnf)) ;non terminals. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
335 (alist '())) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
336 (dolist (nt bnf) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
337 (dolist (rhs (cdr nt)) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
338 (unless (or (< (length rhs) 2) (member (car rhs) nts)) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
339 (if no-inners |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
340 (let ((last (car (last rhs)))) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
341 (unless (member last nts) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
342 (pushnew (cons (car rhs) last) alist :test #'equal))) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
343 ;; Reverse so that the "real" closer gets there first, |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
344 ;; which is important for smie-close-block. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
345 (dolist (term (reverse (cdr rhs))) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
346 (unless (member term nts) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
347 (pushnew (cons (car rhs) term) alist :test #'equal))))))) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
348 (nreverse alist))) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
349 |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
350 (defun smie-bnf-classify (bnf) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
351 "Return a table classifying terminals. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
352 Each terminal can either be an `opener', a `closer', or neither." |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
353 (let ((table (make-hash-table :test #'equal)) |
111622
df422e3ae879
* emacs-lisp/smie.el (smie-bnf-classify): Signal errors for tokens
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111605
diff
changeset
|
354 (nts (mapcar #'car bnf)) |
111382
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
355 (alist '())) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
356 (dolist (category bnf) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
357 (puthash (car category) 'neither table) ;Remove non-terminals. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
358 (dolist (rhs (cdr category)) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
359 (if (null (cdr rhs)) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
360 (puthash (pop rhs) 'neither table) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
361 (let ((first (pop rhs))) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
362 (puthash first |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
363 (if (memq (gethash first table) '(nil opener)) |
111622
df422e3ae879
* emacs-lisp/smie.el (smie-bnf-classify): Signal errors for tokens
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111605
diff
changeset
|
364 'opener |
df422e3ae879
* emacs-lisp/smie.el (smie-bnf-classify): Signal errors for tokens
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111605
diff
changeset
|
365 (unless (member first nts) |
df422e3ae879
* emacs-lisp/smie.el (smie-bnf-classify): Signal errors for tokens
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111605
diff
changeset
|
366 (error "SMIE: token %s is both opener and non-opener" |
df422e3ae879
* emacs-lisp/smie.el (smie-bnf-classify): Signal errors for tokens
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111605
diff
changeset
|
367 first)) |
df422e3ae879
* emacs-lisp/smie.el (smie-bnf-classify): Signal errors for tokens
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111605
diff
changeset
|
368 'neither) |
111382
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
369 table)) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
370 (while (cdr rhs) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
371 (puthash (pop rhs) 'neither table)) ;Remove internals. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
372 (let ((last (pop rhs))) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
373 (puthash last |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
374 (if (memq (gethash last table) '(nil closer)) |
111622
df422e3ae879
* emacs-lisp/smie.el (smie-bnf-classify): Signal errors for tokens
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111605
diff
changeset
|
375 'closer |
df422e3ae879
* emacs-lisp/smie.el (smie-bnf-classify): Signal errors for tokens
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111605
diff
changeset
|
376 (unless (member last nts) |
df422e3ae879
* emacs-lisp/smie.el (smie-bnf-classify): Signal errors for tokens
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111605
diff
changeset
|
377 (error "SMIE: token %s is both closer and non-closer" |
df422e3ae879
* emacs-lisp/smie.el (smie-bnf-classify): Signal errors for tokens
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111605
diff
changeset
|
378 last)) |
df422e3ae879
* emacs-lisp/smie.el (smie-bnf-classify): Signal errors for tokens
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111605
diff
changeset
|
379 'neither) |
111382
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
380 table))))) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
381 (maphash (lambda (tok v) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
382 (when (memq v '(closer opener)) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
383 (push (cons tok v) alist))) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
384 table) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
385 alist)) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
386 |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
387 (defun smie-debug--prec2-cycle (csts) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
388 "Return a cycle in CSTS, assuming there's one. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
389 CSTS is a list of pairs representing arcs in a graph." |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
390 ;; A PATH is of the form (START . REST) where REST is a reverse |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
391 ;; list of nodes through which the path goes. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
392 (let ((paths (mapcar (lambda (pair) (list (car pair) (cdr pair))) csts)) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
393 (cycle nil)) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
394 (while (null cycle) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
395 (dolist (path (prog1 paths (setq paths nil))) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
396 (dolist (cst csts) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
397 (when (eq (car cst) (nth 1 path)) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
398 (if (eq (cdr cst) (car path)) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
399 (setq cycle path) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
400 (push (cons (car path) (cons (cdr cst) (cdr path))) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
401 paths)))))) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
402 (cons (car cycle) (nreverse (cdr cycle))))) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
403 |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
404 (defun smie-debug--describe-cycle (table cycle) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
405 (let ((names |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
406 (mapcar (lambda (val) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
407 (let ((res nil)) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
408 (dolist (elem table) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
409 (if (eq (cdr elem) val) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
410 (push (concat "." (car elem)) res)) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
411 (if (eq (cddr elem) val) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
412 (push (concat (car elem) ".") res))) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
413 (assert res) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
414 res)) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
415 cycle))) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
416 (mapconcat |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
417 (lambda (elems) (mapconcat 'identity elems "=")) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
418 (append names (list (car names))) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
419 " < "))) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
420 |
111605
ca8b605ca70f
* lisp/emacs-lisp/smie.el (smie-prec2->grammar): Obey equality constraints
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111603
diff
changeset
|
421 ;; (defun smie-check-grammar (grammar prec2 &optional dummy) |
ca8b605ca70f
* lisp/emacs-lisp/smie.el (smie-prec2->grammar): Obey equality constraints
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111603
diff
changeset
|
422 ;; (maphash (lambda (k v) |
ca8b605ca70f
* lisp/emacs-lisp/smie.el (smie-prec2->grammar): Obey equality constraints
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111603
diff
changeset
|
423 ;; (when (consp k) |
ca8b605ca70f
* lisp/emacs-lisp/smie.el (smie-prec2->grammar): Obey equality constraints
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111603
diff
changeset
|
424 ;; (let ((left (nth 2 (assoc (car k) grammar))) |
ca8b605ca70f
* lisp/emacs-lisp/smie.el (smie-prec2->grammar): Obey equality constraints
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111603
diff
changeset
|
425 ;; (right (nth 1 (assoc (cdr k) grammar)))) |
ca8b605ca70f
* lisp/emacs-lisp/smie.el (smie-prec2->grammar): Obey equality constraints
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111603
diff
changeset
|
426 ;; (when (and left right) |
ca8b605ca70f
* lisp/emacs-lisp/smie.el (smie-prec2->grammar): Obey equality constraints
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111603
diff
changeset
|
427 ;; (cond |
ca8b605ca70f
* lisp/emacs-lisp/smie.el (smie-prec2->grammar): Obey equality constraints
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111603
diff
changeset
|
428 ;; ((< left right) (assert (eq v '<))) |
ca8b605ca70f
* lisp/emacs-lisp/smie.el (smie-prec2->grammar): Obey equality constraints
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111603
diff
changeset
|
429 ;; ((> left right) (assert (eq v '>))) |
ca8b605ca70f
* lisp/emacs-lisp/smie.el (smie-prec2->grammar): Obey equality constraints
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111603
diff
changeset
|
430 ;; (t (assert (eq v '=)))))))) |
ca8b605ca70f
* lisp/emacs-lisp/smie.el (smie-prec2->grammar): Obey equality constraints
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111603
diff
changeset
|
431 ;; prec2)) |
ca8b605ca70f
* lisp/emacs-lisp/smie.el (smie-prec2->grammar): Obey equality constraints
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111603
diff
changeset
|
432 |
111382
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
433 (put 'smie-prec2->grammar 'pure t) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
434 (defun smie-prec2->grammar (prec2) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
435 "Take a 2D precedence table and turn it into an alist of precedence levels. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
436 PREC2 is a table as returned by `smie-precs->prec2' or |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
437 `smie-bnf->prec2'." |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
438 ;; For each operator, we create two "variables" (corresponding to |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
439 ;; the left and right precedence level), which are represented by |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
440 ;; cons cells. Those are the very cons cells that appear in the |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
441 ;; final `table'. The value of each "variable" is kept in the `car'. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
442 (let ((table ()) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
443 (csts ()) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
444 (eqs ()) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
445 tmp x y) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
446 ;; From `prec2' we construct a list of constraints between |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
447 ;; variables (aka "precedence levels"). These can be either |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
448 ;; equality constraints (in `eqs') or `<' constraints (in `csts'). |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
449 (maphash (lambda (k v) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
450 (when (consp k) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
451 (if (setq tmp (assoc (car k) table)) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
452 (setq x (cddr tmp)) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
453 (setq x (cons nil nil)) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
454 (push (cons (car k) (cons nil x)) table)) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
455 (if (setq tmp (assoc (cdr k) table)) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
456 (setq y (cdr tmp)) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
457 (setq y (cons nil (cons nil nil))) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
458 (push (cons (cdr k) y) table)) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
459 (ecase v |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
460 (= (push (cons x y) eqs)) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
461 (< (push (cons x y) csts)) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
462 (> (push (cons y x) csts))))) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
463 prec2) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
464 ;; First process the equality constraints. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
465 (let ((eqs eqs)) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
466 (while eqs |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
467 (let ((from (caar eqs)) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
468 (to (cdar eqs))) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
469 (setq eqs (cdr eqs)) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
470 (if (eq to from) |
111775
81cac26277b0
* emacs-lisp/smie.el (smie-prec2->grammar): Simplify handling
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111622
diff
changeset
|
471 nil ;Nothing to do. |
111382
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
472 (dolist (other-eq eqs) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
473 (if (eq from (cdr other-eq)) (setcdr other-eq to)) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
474 (when (eq from (car other-eq)) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
475 ;; This can happen because of `assoc' settings in precs |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
476 ;; or because of a rhs like ("op" foo "op"). |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
477 (setcar other-eq to))) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
478 (dolist (cst csts) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
479 (if (eq from (cdr cst)) (setcdr cst to)) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
480 (if (eq from (car cst)) (setcar cst to))))))) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
481 ;; Then eliminate trivial constraints iteratively. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
482 (let ((i 0)) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
483 (while csts |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
484 (let ((rhvs (mapcar 'cdr csts)) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
485 (progress nil)) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
486 (dolist (cst csts) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
487 (unless (memq (car cst) rhvs) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
488 (setq progress t) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
489 ;; We could give each var in a given iteration the same value, |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
490 ;; but we can also give them arbitrarily different values. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
491 ;; Basically, these are vars between which there is no |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
492 ;; constraint (neither equality nor inequality), so |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
493 ;; anything will do. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
494 ;; We give them arbitrary values, which means that we |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
495 ;; replace the "no constraint" case with either > or < |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
496 ;; but not =. The reason we do that is so as to try and |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
497 ;; distinguish associative operators (which will have |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
498 ;; left = right). |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
499 (unless (caar cst) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
500 (setcar (car cst) i) |
111605
ca8b605ca70f
* lisp/emacs-lisp/smie.el (smie-prec2->grammar): Obey equality constraints
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111603
diff
changeset
|
501 ;; (smie-check-grammar table prec2 'step1) |
111382
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
502 (incf i)) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
503 (setq csts (delq cst csts)))) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
504 (unless progress |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
505 (error "Can't resolve the precedence cycle: %s" |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
506 (smie-debug--describe-cycle |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
507 table (smie-debug--prec2-cycle csts))))) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
508 (incf i 10)) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
509 ;; Propagate equalities back to their source. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
510 (dolist (eq (nreverse eqs)) |
111605
ca8b605ca70f
* lisp/emacs-lisp/smie.el (smie-prec2->grammar): Obey equality constraints
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111603
diff
changeset
|
511 (when (null (cadr eq)) |
ca8b605ca70f
* lisp/emacs-lisp/smie.el (smie-prec2->grammar): Obey equality constraints
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111603
diff
changeset
|
512 ;; There's an equality constraint, but we still haven't given |
ca8b605ca70f
* lisp/emacs-lisp/smie.el (smie-prec2->grammar): Obey equality constraints
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111603
diff
changeset
|
513 ;; it a value: that means it binds tighter than anything else, |
ca8b605ca70f
* lisp/emacs-lisp/smie.el (smie-prec2->grammar): Obey equality constraints
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111603
diff
changeset
|
514 ;; and it can't be an opener/closer (those don't have equality |
ca8b605ca70f
* lisp/emacs-lisp/smie.el (smie-prec2->grammar): Obey equality constraints
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111603
diff
changeset
|
515 ;; constraints). |
ca8b605ca70f
* lisp/emacs-lisp/smie.el (smie-prec2->grammar): Obey equality constraints
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111603
diff
changeset
|
516 ;; So set it here rather than below since doing it below |
ca8b605ca70f
* lisp/emacs-lisp/smie.el (smie-prec2->grammar): Obey equality constraints
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111603
diff
changeset
|
517 ;; makes it more difficult to obey the equality constraints. |
ca8b605ca70f
* lisp/emacs-lisp/smie.el (smie-prec2->grammar): Obey equality constraints
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111603
diff
changeset
|
518 (setcar (cdr eq) i) |
ca8b605ca70f
* lisp/emacs-lisp/smie.el (smie-prec2->grammar): Obey equality constraints
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111603
diff
changeset
|
519 (incf i)) |
ca8b605ca70f
* lisp/emacs-lisp/smie.el (smie-prec2->grammar): Obey equality constraints
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111603
diff
changeset
|
520 (assert (or (null (caar eq)) (eq (caar eq) (cadr eq)))) |
ca8b605ca70f
* lisp/emacs-lisp/smie.el (smie-prec2->grammar): Obey equality constraints
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111603
diff
changeset
|
521 (setcar (car eq) (cadr eq)) |
ca8b605ca70f
* lisp/emacs-lisp/smie.el (smie-prec2->grammar): Obey equality constraints
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111603
diff
changeset
|
522 ;; (smie-check-grammar table prec2 'step2) |
ca8b605ca70f
* lisp/emacs-lisp/smie.el (smie-prec2->grammar): Obey equality constraints
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111603
diff
changeset
|
523 ) |
111775
81cac26277b0
* emacs-lisp/smie.el (smie-prec2->grammar): Simplify handling
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111622
diff
changeset
|
524 ;; Finally, fill in the remaining vars (which did not appear on the |
81cac26277b0
* emacs-lisp/smie.el (smie-prec2->grammar): Simplify handling
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111622
diff
changeset
|
525 ;; left side of any < constraint). |
81cac26277b0
* emacs-lisp/smie.el (smie-prec2->grammar): Simplify handling
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111622
diff
changeset
|
526 (dolist (x table) |
81cac26277b0
* emacs-lisp/smie.el (smie-prec2->grammar): Simplify handling
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111622
diff
changeset
|
527 (unless (nth 1 x) |
81cac26277b0
* emacs-lisp/smie.el (smie-prec2->grammar): Simplify handling
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111622
diff
changeset
|
528 (setf (nth 1 x) i) |
81cac26277b0
* emacs-lisp/smie.el (smie-prec2->grammar): Simplify handling
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111622
diff
changeset
|
529 (incf i)) ;See other (incf i) above. |
81cac26277b0
* emacs-lisp/smie.el (smie-prec2->grammar): Simplify handling
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111622
diff
changeset
|
530 (unless (nth 2 x) |
81cac26277b0
* emacs-lisp/smie.el (smie-prec2->grammar): Simplify handling
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111622
diff
changeset
|
531 (setf (nth 2 x) i) |
81cac26277b0
* emacs-lisp/smie.el (smie-prec2->grammar): Simplify handling
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111622
diff
changeset
|
532 (incf i)))) ;See other (incf i) above. |
81cac26277b0
* emacs-lisp/smie.el (smie-prec2->grammar): Simplify handling
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111622
diff
changeset
|
533 ;; Mark closers and openers. |
81cac26277b0
* emacs-lisp/smie.el (smie-prec2->grammar): Simplify handling
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111622
diff
changeset
|
534 (dolist (x (gethash :smie-open/close-alist prec2)) |
81cac26277b0
* emacs-lisp/smie.el (smie-prec2->grammar): Simplify handling
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111622
diff
changeset
|
535 (let* ((token (car x)) |
81cac26277b0
* emacs-lisp/smie.el (smie-prec2->grammar): Simplify handling
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111622
diff
changeset
|
536 (cons (case (cdr x) |
81cac26277b0
* emacs-lisp/smie.el (smie-prec2->grammar): Simplify handling
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111622
diff
changeset
|
537 (closer (cddr (assoc token table))) |
81cac26277b0
* emacs-lisp/smie.el (smie-prec2->grammar): Simplify handling
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111622
diff
changeset
|
538 (opener (cdr (assoc token table)))))) |
81cac26277b0
* emacs-lisp/smie.el (smie-prec2->grammar): Simplify handling
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111622
diff
changeset
|
539 (assert (numberp (car cons))) |
81cac26277b0
* emacs-lisp/smie.el (smie-prec2->grammar): Simplify handling
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111622
diff
changeset
|
540 (setf (car cons) (list (car cons))))) |
111382
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
541 (let ((ca (gethash :smie-closer-alist prec2))) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
542 (when ca (push (cons :smie-closer-alist ca) table))) |
111605
ca8b605ca70f
* lisp/emacs-lisp/smie.el (smie-prec2->grammar): Obey equality constraints
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111603
diff
changeset
|
543 ;; (smie-check-grammar table prec2 'step3) |
111382
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
544 table)) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
545 |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
546 ;;; Parsing using a precedence level table. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
547 |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
548 (defvar smie-grammar 'unset |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
549 "List of token parsing info. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
550 This list is normally built by `smie-prec2->grammar'. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
551 Each element is of the form (TOKEN LEFT-LEVEL RIGHT-LEVEL). |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
552 Parsing is done using an operator precedence parser. |
111622
df422e3ae879
* emacs-lisp/smie.el (smie-bnf-classify): Signal errors for tokens
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111605
diff
changeset
|
553 LEFT-LEVEL and RIGHT-LEVEL can be either numbers or a list, where a list |
111382
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
554 means that this operator does not bind on the corresponding side, |
111622
df422e3ae879
* emacs-lisp/smie.el (smie-bnf-classify): Signal errors for tokens
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111605
diff
changeset
|
555 e.g. a LEFT-LEVEL of nil means this is a token that behaves somewhat like |
111382
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
556 an open-paren, whereas a RIGHT-LEVEL of nil would correspond to something |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
557 like a close-paren.") |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
558 |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
559 (defvar smie-forward-token-function 'smie-default-forward-token |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
560 "Function to scan forward for the next token. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
561 Called with no argument should return a token and move to its end. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
562 If no token is found, return nil or the empty string. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
563 It can return nil when bumping into a parenthesis, which lets SMIE |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
564 use syntax-tables to handle them in efficient C code.") |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
565 |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
566 (defvar smie-backward-token-function 'smie-default-backward-token |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
567 "Function to scan backward the previous token. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
568 Same calling convention as `smie-forward-token-function' except |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
569 it should move backward to the beginning of the previous token.") |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
570 |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
571 (defalias 'smie-op-left 'car) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
572 (defalias 'smie-op-right 'cadr) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
573 |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
574 (defun smie-default-backward-token () |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
575 (forward-comment (- (point))) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
576 (buffer-substring-no-properties |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
577 (point) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
578 (progn (if (zerop (skip-syntax-backward ".")) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
579 (skip-syntax-backward "w_'")) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
580 (point)))) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
581 |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
582 (defun smie-default-forward-token () |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
583 (forward-comment (point-max)) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
584 (buffer-substring-no-properties |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
585 (point) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
586 (progn (if (zerop (skip-syntax-forward ".")) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
587 (skip-syntax-forward "w_'")) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
588 (point)))) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
589 |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
590 (defun smie--associative-p (toklevels) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
591 ;; in "a + b + c" we want to stop at each +, but in |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
592 ;; "if a then b elsif c then d else c" we don't want to stop at each keyword. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
593 ;; To distinguish the two cases, we made smie-prec2->grammar choose |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
594 ;; different levels for each part of "if a then b else c", so that |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
595 ;; by checking if the left-level is equal to the right level, we can |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
596 ;; figure out that it's an associative operator. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
597 ;; This is not 100% foolproof, tho, since the "elsif" will have to have |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
598 ;; equal left and right levels (since it's optional), so smie-next-sexp |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
599 ;; has to be careful to distinguish those different cases. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
600 (eq (smie-op-left toklevels) (smie-op-right toklevels))) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
601 |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
602 (defun smie-next-sexp (next-token next-sexp op-forw op-back halfsexp) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
603 "Skip over one sexp. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
604 NEXT-TOKEN is a function of no argument that moves forward by one |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
605 token (after skipping comments if needed) and returns it. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
606 NEXT-SEXP is a lower-level function to skip one sexp. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
607 OP-FORW is the accessor to the forward level of the level data. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
608 OP-BACK is the accessor to the backward level of the level data. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
609 HALFSEXP if non-nil, means skip over a partial sexp if needed. I.e. if the |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
610 first token we see is an operator, skip over its left-hand-side argument. |
111775
81cac26277b0
* emacs-lisp/smie.el (smie-prec2->grammar): Simplify handling
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111622
diff
changeset
|
611 HALFSEXP can also be a token, in which case it means to parse as if |
81cac26277b0
* emacs-lisp/smie.el (smie-prec2->grammar): Simplify handling
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111622
diff
changeset
|
612 we had just successfully passed this token. |
111382
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
613 Possible return values: |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
614 (FORW-LEVEL POS TOKEN): we couldn't skip TOKEN because its back-level |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
615 is too high. FORW-LEVEL is the forw-level of TOKEN, |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
616 POS is its start position in the buffer. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
617 (t POS TOKEN): same thing when we bump on the wrong side of a paren. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
618 (nil POS TOKEN): we skipped over a paren-like pair. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
619 nil: we skipped over an identifier, matched parentheses, ..." |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
620 (catch 'return |
111775
81cac26277b0
* emacs-lisp/smie.el (smie-prec2->grammar): Simplify handling
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111622
diff
changeset
|
621 (let ((levels |
81cac26277b0
* emacs-lisp/smie.el (smie-prec2->grammar): Simplify handling
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111622
diff
changeset
|
622 (if (stringp halfsexp) |
81cac26277b0
* emacs-lisp/smie.el (smie-prec2->grammar): Simplify handling
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111622
diff
changeset
|
623 (prog1 (list (cdr (assoc halfsexp smie-grammar))) |
81cac26277b0
* emacs-lisp/smie.el (smie-prec2->grammar): Simplify handling
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111622
diff
changeset
|
624 (setq halfsexp nil))))) |
111382
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
625 (while |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
626 (let* ((pos (point)) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
627 (token (funcall next-token)) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
628 (toklevels (cdr (assoc token smie-grammar)))) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
629 (cond |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
630 ((null toklevels) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
631 (when (zerop (length token)) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
632 (condition-case err |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
633 (progn (goto-char pos) (funcall next-sexp 1) nil) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
634 (scan-error (throw 'return |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
635 (list t (caddr err) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
636 (buffer-substring-no-properties |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
637 (caddr err) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
638 (+ (caddr err) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
639 (if (< (point) (caddr err)) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
640 -1 1))))))) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
641 (if (eq pos (point)) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
642 ;; We did not move, so let's abort the loop. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
643 (throw 'return (list t (point)))))) |
111622
df422e3ae879
* emacs-lisp/smie.el (smie-bnf-classify): Signal errors for tokens
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111605
diff
changeset
|
644 ((not (numberp (funcall op-back toklevels))) |
111382
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
645 ;; A token like a paren-close. |
111622
df422e3ae879
* emacs-lisp/smie.el (smie-bnf-classify): Signal errors for tokens
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111605
diff
changeset
|
646 (assert (numberp ; Otherwise, why mention it in smie-grammar. |
df422e3ae879
* emacs-lisp/smie.el (smie-bnf-classify): Signal errors for tokens
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111605
diff
changeset
|
647 (funcall op-forw toklevels))) |
111382
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
648 (push toklevels levels)) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
649 (t |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
650 (while (and levels (< (funcall op-back toklevels) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
651 (funcall op-forw (car levels)))) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
652 (setq levels (cdr levels))) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
653 (cond |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
654 ((null levels) |
111622
df422e3ae879
* emacs-lisp/smie.el (smie-bnf-classify): Signal errors for tokens
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111605
diff
changeset
|
655 (if (and halfsexp (numberp (funcall op-forw toklevels))) |
111382
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
656 (push toklevels levels) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
657 (throw 'return |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
658 (prog1 (list (or (car toklevels) t) (point) token) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
659 (goto-char pos))))) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
660 (t |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
661 (let ((lastlevels levels)) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
662 (if (and levels (= (funcall op-back toklevels) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
663 (funcall op-forw (car levels)))) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
664 (setq levels (cdr levels))) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
665 ;; We may have found a match for the previously pending |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
666 ;; operator. Is this the end? |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
667 (cond |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
668 ;; Keep looking as long as we haven't matched the |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
669 ;; topmost operator. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
670 (levels |
111622
df422e3ae879
* emacs-lisp/smie.el (smie-bnf-classify): Signal errors for tokens
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111605
diff
changeset
|
671 (if (numberp (funcall op-forw toklevels)) |
111382
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
672 (push toklevels levels))) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
673 ;; We matched the topmost operator. If the new operator |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
674 ;; is the last in the corresponding BNF rule, we're done. |
111622
df422e3ae879
* emacs-lisp/smie.el (smie-bnf-classify): Signal errors for tokens
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111605
diff
changeset
|
675 ((not (numberp (funcall op-forw toklevels))) |
111382
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
676 ;; It is the last element, let's stop here. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
677 (throw 'return (list nil (point) token))) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
678 ;; If the new operator is not the last in the BNF rule, |
111603
c901fac3b428
* lisp/emacs-lisp/smie.el (smie-rule-parent, smie-indent--rule):
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111382
diff
changeset
|
679 ;; and is not associative, it's one of the inner operators |
111382
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
680 ;; (like the "in" in "let .. in .. end"), so keep looking. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
681 ((not (smie--associative-p toklevels)) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
682 (push toklevels levels)) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
683 ;; The new operator is associative. Two cases: |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
684 ;; - it's really just an associative operator (like + or ;) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
685 ;; in which case we should have stopped right before. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
686 ((and lastlevels |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
687 (smie--associative-p (car lastlevels))) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
688 (throw 'return |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
689 (prog1 (list (or (car toklevels) t) (point) token) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
690 (goto-char pos)))) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
691 ;; - it's an associative operator within a larger construct |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
692 ;; (e.g. an "elsif"), so we should just ignore it and keep |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
693 ;; looking for the closing element. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
694 (t (setq levels lastlevels)))))))) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
695 levels) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
696 (setq halfsexp nil))))) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
697 |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
698 (defun smie-backward-sexp (&optional halfsexp) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
699 "Skip over one sexp. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
700 HALFSEXP if non-nil, means skip over a partial sexp if needed. I.e. if the |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
701 first token we see is an operator, skip over its left-hand-side argument. |
111775
81cac26277b0
* emacs-lisp/smie.el (smie-prec2->grammar): Simplify handling
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111622
diff
changeset
|
702 HALFSEXP can also be a token, in which case we should skip the text |
81cac26277b0
* emacs-lisp/smie.el (smie-prec2->grammar): Simplify handling
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111622
diff
changeset
|
703 assuming it is the left-hand-side argument of that token. |
111382
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
704 Possible return values: |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
705 (LEFT-LEVEL POS TOKEN): we couldn't skip TOKEN because its right-level |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
706 is too high. LEFT-LEVEL is the left-level of TOKEN, |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
707 POS is its start position in the buffer. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
708 (t POS TOKEN): same thing but for an open-paren or the beginning of buffer. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
709 (nil POS TOKEN): we skipped over a paren-like pair. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
710 nil: we skipped over an identifier, matched parentheses, ..." |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
711 (smie-next-sexp |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
712 (indirect-function smie-backward-token-function) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
713 (indirect-function 'backward-sexp) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
714 (indirect-function 'smie-op-left) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
715 (indirect-function 'smie-op-right) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
716 halfsexp)) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
717 |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
718 (defun smie-forward-sexp (&optional halfsexp) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
719 "Skip over one sexp. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
720 HALFSEXP if non-nil, means skip over a partial sexp if needed. I.e. if the |
111775
81cac26277b0
* emacs-lisp/smie.el (smie-prec2->grammar): Simplify handling
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111622
diff
changeset
|
721 first token we see is an operator, skip over its right-hand-side argument. |
81cac26277b0
* emacs-lisp/smie.el (smie-prec2->grammar): Simplify handling
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111622
diff
changeset
|
722 HALFSEXP can also be a token, in which case we should skip the text |
81cac26277b0
* emacs-lisp/smie.el (smie-prec2->grammar): Simplify handling
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111622
diff
changeset
|
723 assuming it is the right-hand-side argument of that token. |
111382
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
724 Possible return values: |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
725 (RIGHT-LEVEL POS TOKEN): we couldn't skip TOKEN because its left-level |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
726 is too high. RIGHT-LEVEL is the right-level of TOKEN, |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
727 POS is its end position in the buffer. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
728 (t POS TOKEN): same thing but for an open-paren or the beginning of buffer. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
729 (nil POS TOKEN): we skipped over a paren-like pair. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
730 nil: we skipped over an identifier, matched parentheses, ..." |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
731 (smie-next-sexp |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
732 (indirect-function smie-forward-token-function) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
733 (indirect-function 'forward-sexp) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
734 (indirect-function 'smie-op-right) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
735 (indirect-function 'smie-op-left) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
736 halfsexp)) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
737 |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
738 ;;; Miscellanous commands using the precedence parser. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
739 |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
740 (defun smie-backward-sexp-command (&optional n) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
741 "Move backward through N logical elements." |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
742 (interactive "^p") |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
743 (smie-forward-sexp-command (- n))) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
744 |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
745 (defun smie-forward-sexp-command (&optional n) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
746 "Move forward through N logical elements." |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
747 (interactive "^p") |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
748 (let ((forw (> n 0)) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
749 (forward-sexp-function nil)) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
750 (while (/= n 0) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
751 (setq n (- n (if forw 1 -1))) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
752 (let ((pos (point)) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
753 (res (if forw |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
754 (smie-forward-sexp 'halfsexp) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
755 (smie-backward-sexp 'halfsexp)))) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
756 (if (and (car res) (= pos (point)) (not (if forw (eobp) (bobp)))) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
757 (signal 'scan-error |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
758 (list "Containing expression ends prematurely" |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
759 (cadr res) (cadr res))) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
760 nil))))) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
761 |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
762 (defvar smie-closer-alist nil |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
763 "Alist giving the closer corresponding to an opener.") |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
764 |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
765 (defun smie-close-block () |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
766 "Close the closest surrounding block." |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
767 (interactive) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
768 (let ((closer |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
769 (save-excursion |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
770 (backward-up-list 1) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
771 (if (looking-at "\\s(") |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
772 (string (cdr (syntax-after (point)))) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
773 (let* ((open (funcall smie-forward-token-function)) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
774 (closer (cdr (assoc open smie-closer-alist))) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
775 (levels (list (assoc open smie-grammar))) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
776 (seen '()) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
777 (found '())) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
778 (cond |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
779 ;; Even if we improve the auto-computation of closers, |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
780 ;; there are still cases where we need manual |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
781 ;; intervention, e.g. for Octave's use of `until' |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
782 ;; as a pseudo-closer of `do'. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
783 (closer) |
111622
df422e3ae879
* emacs-lisp/smie.el (smie-bnf-classify): Signal errors for tokens
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111605
diff
changeset
|
784 ((or (equal levels '(nil)) (numberp (nth 1 (car levels)))) |
111382
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
785 (error "Doesn't look like a block")) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
786 (t |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
787 ;; Now that smie-setup automatically sets smie-closer-alist |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
788 ;; from the BNF, this is not really needed any more. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
789 (while levels |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
790 (let ((level (pop levels))) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
791 (dolist (other smie-grammar) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
792 (when (and (eq (nth 2 level) (nth 1 other)) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
793 (not (memq other seen))) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
794 (push other seen) |
111622
df422e3ae879
* emacs-lisp/smie.el (smie-bnf-classify): Signal errors for tokens
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111605
diff
changeset
|
795 (if (numberp (nth 2 other)) |
111382
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
796 (push other levels) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
797 (push (car other) found)))))) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
798 (cond |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
799 ((null found) (error "No known closer for opener %s" open)) |
111775
81cac26277b0
* emacs-lisp/smie.el (smie-prec2->grammar): Simplify handling
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111622
diff
changeset
|
800 ;; What should we do if there are various closers? |
111382
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
801 (t (car found)))))))))) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
802 (unless (save-excursion (skip-chars-backward " \t") (bolp)) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
803 (newline)) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
804 (insert closer) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
805 (if (save-excursion (skip-chars-forward " \t") (eolp)) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
806 (indent-according-to-mode) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
807 (reindent-then-newline-and-indent)))) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
808 |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
809 (defun smie-down-list (&optional arg) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
810 "Move forward down one level paren-like blocks. Like `down-list'. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
811 With argument ARG, do this that many times. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
812 A negative argument means move backward but still go down a level. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
813 This command assumes point is not in a string or comment." |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
814 (interactive "p") |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
815 (let ((start (point)) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
816 (inc (if (< arg 0) -1 1)) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
817 (offset (if (< arg 0) 1 0)) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
818 (next-token (if (< arg 0) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
819 smie-backward-token-function |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
820 smie-forward-token-function))) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
821 (while (/= arg 0) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
822 (setq arg (- arg inc)) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
823 (while |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
824 (let* ((pos (point)) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
825 (token (funcall next-token)) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
826 (levels (assoc token smie-grammar))) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
827 (cond |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
828 ((zerop (length token)) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
829 (if (if (< inc 0) (looking-back "\\s(\\|\\s)" (1- (point))) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
830 (looking-at "\\s(\\|\\s)")) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
831 ;; Go back to `start' in case of an error. This presumes |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
832 ;; none of the token we've found until now include a ( or ). |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
833 (progn (goto-char start) (down-list inc) nil) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
834 (forward-sexp inc) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
835 (/= (point) pos))) |
111622
df422e3ae879
* emacs-lisp/smie.el (smie-bnf-classify): Signal errors for tokens
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111605
diff
changeset
|
836 ((and levels (not (numberp (nth (+ 1 offset) levels)))) nil) |
df422e3ae879
* emacs-lisp/smie.el (smie-bnf-classify): Signal errors for tokens
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111605
diff
changeset
|
837 ((and levels (not (numberp (nth (- 2 offset) levels)))) |
111382
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
838 (let ((end (point))) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
839 (goto-char start) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
840 (signal 'scan-error |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
841 (list "Containing expression ends prematurely" |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
842 pos end)))) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
843 (t))))))) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
844 |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
845 (defvar smie-blink-matching-triggers '(?\s ?\n) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
846 "Chars which might trigger `blink-matching-open'. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
847 These can include the final chars of end-tokens, or chars that are |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
848 typically inserted right after an end token. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
849 I.e. a good choice can be: |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
850 (delete-dups |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
851 (mapcar (lambda (kw) (aref (cdr kw) (1- (length (cdr kw))))) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
852 smie-closer-alist))") |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
853 |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
854 (defcustom smie-blink-matching-inners t |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
855 "Whether SMIE should blink to matching opener for inner keywords. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
856 If non-nil, it will blink not only for \"begin..end\" but also for \"if...else\"." |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
857 :type 'boolean |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
858 :group 'smie) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
859 |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
860 (defun smie-blink-matching-check (start end) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
861 (save-excursion |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
862 (goto-char end) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
863 (let ((ender (funcall smie-backward-token-function))) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
864 (cond |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
865 ((not (and ender (rassoc ender smie-closer-alist))) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
866 ;; This not is one of the begin..end we know how to check. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
867 (blink-matching-check-mismatch start end)) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
868 ((not start) t) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
869 ((eq t (car (rassoc ender smie-closer-alist))) nil) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
870 (t |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
871 (goto-char start) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
872 (let ((starter (funcall smie-forward-token-function))) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
873 (not (member (cons starter ender) smie-closer-alist)))))))) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
874 |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
875 (defun smie-blink-matching-open () |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
876 "Blink the matching opener when applicable. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
877 This uses SMIE's tables and is expected to be placed on `post-self-insert-hook'." |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
878 (let ((pos (point)) ;Position after the close token. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
879 token) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
880 (when (and blink-matching-paren |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
881 smie-closer-alist ; Optimization. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
882 (or (eq (char-before) last-command-event) ;; Sanity check. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
883 (save-excursion |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
884 (or (progn (skip-chars-backward " \t") |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
885 (setq pos (point)) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
886 (eq (char-before) last-command-event)) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
887 (progn (skip-chars-backward " \n\t") |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
888 (setq pos (point)) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
889 (eq (char-before) last-command-event))))) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
890 (memq last-command-event smie-blink-matching-triggers) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
891 (not (nth 8 (syntax-ppss)))) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
892 (save-excursion |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
893 (setq token (funcall smie-backward-token-function)) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
894 (when (and (eq (point) (1- pos)) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
895 (= 1 (length token)) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
896 (not (rassoc token smie-closer-alist))) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
897 ;; The trigger char is itself a token but is not one of the |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
898 ;; closers (e.g. ?\; in Octave mode), so go back to the |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
899 ;; previous token. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
900 (setq pos (point)) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
901 (setq token (funcall smie-backward-token-function))) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
902 (when (rassoc token smie-closer-alist) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
903 ;; We're after a close token. Let's still make sure we |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
904 ;; didn't skip a comment to find that token. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
905 (funcall smie-forward-token-function) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
906 (when (and (save-excursion |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
907 ;; Skip the trigger char, if applicable. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
908 (if (eq (char-after) last-command-event) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
909 (forward-char 1)) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
910 (if (eq ?\n last-command-event) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
911 ;; Skip any auto-indentation, if applicable. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
912 (skip-chars-forward " \t")) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
913 (>= (point) pos)) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
914 ;; If token ends with a trigger char, don't blink for |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
915 ;; anything else than this trigger char, lest we'd blink |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
916 ;; both when inserting the trigger char and when |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
917 ;; inserting a subsequent trigger char like SPC. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
918 (or (eq (point) pos) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
919 (not (memq (char-before) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
920 smie-blink-matching-triggers))) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
921 (or smie-blink-matching-inners |
111622
df422e3ae879
* emacs-lisp/smie.el (smie-bnf-classify): Signal errors for tokens
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111605
diff
changeset
|
922 (not (numberp (nth 2 (assoc token smie-grammar)))))) |
111382
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
923 ;; The major mode might set blink-matching-check-function |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
924 ;; buffer-locally so that interactive calls to |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
925 ;; blink-matching-open work right, but let's not presume |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
926 ;; that's the case. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
927 (let ((blink-matching-check-function #'smie-blink-matching-check)) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
928 (blink-matching-open)))))))) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
929 |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
930 ;;; The indentation engine. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
931 |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
932 (defcustom smie-indent-basic 4 |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
933 "Basic amount of indentation." |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
934 :type 'integer |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
935 :group 'smie) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
936 |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
937 (defvar smie-rules-function 'ignore |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
938 "Function providing the indentation rules. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
939 It takes two arguments METHOD and ARG where the meaning of ARG |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
940 and the expected return value depends on METHOD. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
941 METHOD can be: |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
942 - :after, in which case ARG is a token and the function should return the |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
943 OFFSET to use for indentation after ARG. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
944 - :before, in which case ARG is a token and the function should return the |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
945 OFFSET to use to indent ARG itself. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
946 - :elem, in which case the function should return either: |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
947 - the offset to use to indent function arguments (ARG = `arg') |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
948 - the basic indentation step (ARG = `basic'). |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
949 - :list-intro, in which case ARG is a token and the function should return |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
950 non-nil if TOKEN is followed by a list of expressions (not separated by any |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
951 token) rather than an expression. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
952 |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
953 When ARG is a token, the function is called with point just before that token. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
954 A return value of nil always means to fallback on the default behavior, so the |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
955 function should return nil for arguments it does not expect. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
956 |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
957 OFFSET can be: |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
958 nil use the default indentation rule. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
959 `(column . COLUMN) indent to column COLUMN. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
960 NUMBER offset by NUMBER, relative to a base token |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
961 which is the current token for :after and |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
962 its parent for :before. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
963 |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
964 The functions whose name starts with \"smie-rule-\" are helper functions |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
965 designed specifically for use in this function.") |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
966 |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
967 (defalias 'smie-rule-hanging-p 'smie-indent--hanging-p) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
968 (defun smie-indent--hanging-p () |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
969 "Return non-nil if the current token is \"hanging\". |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
970 A hanging keyword is one that's at the end of a line except it's not at |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
971 the beginning of a line." |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
972 (and (not (smie-indent--bolp)) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
973 (save-excursion |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
974 (<= (line-end-position) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
975 (progn |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
976 (when (zerop (length (funcall smie-forward-token-function))) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
977 ;; Could be an open-paren. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
978 (forward-char 1)) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
979 (skip-chars-forward " \t") |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
980 (or (eolp) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
981 (and (looking-at comment-start-skip) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
982 (forward-comment (point-max)))) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
983 (point)))))) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
984 |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
985 (defalias 'smie-rule-bolp 'smie-indent--bolp) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
986 (defun smie-indent--bolp () |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
987 "Return non-nil if the current token is the first on the line." |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
988 (save-excursion (skip-chars-backward " \t") (bolp))) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
989 |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
990 ;; Dynamically scoped. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
991 (defvar smie--parent) (defvar smie--after) (defvar smie--token) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
992 |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
993 (defun smie-indent--parent () |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
994 (or smie--parent |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
995 (save-excursion |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
996 (let* ((pos (point)) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
997 (tok (funcall smie-forward-token-function))) |
111622
df422e3ae879
* emacs-lisp/smie.el (smie-bnf-classify): Signal errors for tokens
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111605
diff
changeset
|
998 (unless (numberp (cadr (assoc tok smie-grammar))) |
111382
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
999 (goto-char pos)) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1000 (setq smie--parent |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1001 (smie-backward-sexp 'halfsexp)))))) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1002 |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1003 (defun smie-rule-parent-p (&rest parents) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1004 "Return non-nil if the current token's parent is among PARENTS. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1005 Only meaningful when called from within `smie-rules-function'." |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1006 (member (nth 2 (smie-indent--parent)) parents)) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1007 |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1008 (defun smie-rule-next-p (&rest tokens) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1009 "Return non-nil if the next token is among TOKENS. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1010 Only meaningful when called from within `smie-rules-function'." |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1011 (let ((next |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1012 (save-excursion |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1013 (unless smie--after |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1014 (smie-indent-forward-token) (setq smie--after (point))) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1015 (goto-char smie--after) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1016 (smie-indent-forward-token)))) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1017 (member (car next) tokens))) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1018 |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1019 (defun smie-rule-prev-p (&rest tokens) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1020 "Return non-nil if the previous token is among TOKENS." |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1021 (let ((prev (save-excursion |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1022 (smie-indent-backward-token)))) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1023 (member (car prev) tokens))) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1024 |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1025 (defun smie-rule-sibling-p () |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1026 "Return non-nil if the parent is actually a sibling. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1027 Only meaningful when called from within `smie-rules-function'." |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1028 (eq (car (smie-indent--parent)) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1029 (cadr (assoc smie--token smie-grammar)))) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1030 |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1031 (defun smie-rule-parent (&optional offset) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1032 "Align with parent. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1033 If non-nil, OFFSET should be an integer giving an additional offset to apply. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1034 Only meaningful when called from within `smie-rules-function'." |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1035 (save-excursion |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1036 (goto-char (cadr (smie-indent--parent))) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1037 (cons 'column |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1038 (+ (or offset 0) |
111603
c901fac3b428
* lisp/emacs-lisp/smie.el (smie-rule-parent, smie-indent--rule):
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111382
diff
changeset
|
1039 ;; Use smie-indent-virtual when indenting relative to an opener: |
c901fac3b428
* lisp/emacs-lisp/smie.el (smie-rule-parent, smie-indent--rule):
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111382
diff
changeset
|
1040 ;; this will also by default use current-column unless |
c901fac3b428
* lisp/emacs-lisp/smie.el (smie-rule-parent, smie-indent--rule):
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111382
diff
changeset
|
1041 ;; that opener is hanging, but will additionally consult |
c901fac3b428
* lisp/emacs-lisp/smie.el (smie-rule-parent, smie-indent--rule):
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111382
diff
changeset
|
1042 ;; rules-function, so it gives it a chance to tweak |
c901fac3b428
* lisp/emacs-lisp/smie.el (smie-rule-parent, smie-indent--rule):
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111382
diff
changeset
|
1043 ;; indentation (e.g. by forcing indentation relative to |
c901fac3b428
* lisp/emacs-lisp/smie.el (smie-rule-parent, smie-indent--rule):
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111382
diff
changeset
|
1044 ;; its own parent, as in fn a => fn b => fn c =>). |
111622
df422e3ae879
* emacs-lisp/smie.el (smie-bnf-classify): Signal errors for tokens
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111605
diff
changeset
|
1045 (if (or (listp (car smie--parent)) (smie-indent--hanging-p)) |
111603
c901fac3b428
* lisp/emacs-lisp/smie.el (smie-rule-parent, smie-indent--rule):
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111382
diff
changeset
|
1046 (smie-indent-virtual) (current-column)))))) |
111382
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1047 |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1048 (defvar smie-rule-separator-outdent 2) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1049 |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1050 (defun smie-indent--separator-outdent () |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1051 ;; FIXME: Here we actually have several reasonable behaviors. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1052 ;; E.g. for a parent token of "FOO" and a separator ";" we may want to: |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1053 ;; 1- left-align ; with FOO. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1054 ;; 2- right-align ; with FOO. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1055 ;; 3- align content after ; with content after FOO. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1056 ;; 4- align content plus add/remove spaces so as to align ; with FOO. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1057 ;; Currently, we try to align the contents (option 3) which actually behaves |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1058 ;; just like option 2 (if the number of spaces after FOO and ; is equal). |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1059 (let ((afterpos (save-excursion |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1060 (let ((tok (funcall smie-forward-token-function))) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1061 (unless tok |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1062 (with-demoted-errors |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1063 (error "smie-rule-separator: can't skip token %s" |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1064 smie--token)))) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1065 (skip-chars-forward " ") |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1066 (unless (eolp) (point))))) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1067 (or (and afterpos |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1068 ;; This should always be true, unless |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1069 ;; smie-forward-token-function skipped a \n. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1070 (< afterpos (line-end-position)) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1071 (- afterpos (point))) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1072 smie-rule-separator-outdent))) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1073 |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1074 (defun smie-rule-separator (method) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1075 "Indent current token as a \"separator\". |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1076 By \"separator\", we mean here a token whose sole purpose is to separate |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1077 various elements within some enclosing syntactic construct, and which does |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1078 not have any semantic significance in itself (i.e. it would typically no exist |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1079 as a node in an abstract syntax tree). |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1080 Such a token is expected to have an associative syntax and be closely tied |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1081 to its syntactic parent. Typical examples are \",\" in lists of arguments |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1082 \(enclosed inside parentheses), or \";\" in sequences of instructions (enclosed |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1083 in a {..} or begin..end block). |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1084 METHOD should be the method name that was passed to `smie-rules-function'. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1085 Only meaningful when called from within `smie-rules-function'." |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1086 ;; FIXME: The code below works OK for cases where the separators |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1087 ;; are placed consistently always at beginning or always at the end, |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1088 ;; but not if some are at the beginning and others are at the end. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1089 ;; I.e. it gets confused in cases such as: |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1090 ;; ( a |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1091 ;; , a, |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1092 ;; b |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1093 ;; , c, |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1094 ;; d |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1095 ;; ) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1096 ;; |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1097 ;; Assuming token is associative, the default rule for associative |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1098 ;; tokens (which assumes an infix operator) works fine for many cases. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1099 ;; We mostly need to take care of the case where token is at beginning of |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1100 ;; line, in which case we want to align it with its enclosing parent. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1101 (cond |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1102 ((and (eq method :before) (smie-rule-bolp) (not (smie-rule-sibling-p))) |
111603
c901fac3b428
* lisp/emacs-lisp/smie.el (smie-rule-parent, smie-indent--rule):
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111382
diff
changeset
|
1103 (let ((parent-col (cdr (smie-rule-parent))) |
111382
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1104 (parent-pos-col ;FIXME: we knew this when computing smie--parent. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1105 (save-excursion |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1106 (goto-char (cadr smie--parent)) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1107 (smie-indent-forward-token) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1108 (forward-comment (point-max)) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1109 (current-column)))) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1110 (cons 'column |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1111 (max parent-col |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1112 (min parent-pos-col |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1113 (- parent-pos-col (smie-indent--separator-outdent))))))) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1114 ((and (eq method :after) (smie-indent--bolp)) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1115 (smie-indent--separator-outdent)))) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1116 |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1117 (defun smie-indent--offset (elem) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1118 (or (funcall smie-rules-function :elem elem) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1119 (if (not (eq elem 'basic)) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1120 (funcall smie-rules-function :elem 'basic)) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1121 smie-indent-basic)) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1122 |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1123 (defun smie-indent--rule (method token |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1124 ;; FIXME: Too many parameters. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1125 &optional after parent base-pos) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1126 "Compute indentation column according to `indent-rule-functions'. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1127 METHOD and TOKEN are passed to `indent-rule-functions'. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1128 AFTER is the position after TOKEN, if known. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1129 PARENT is the parent info returned by `smie-backward-sexp', if known. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1130 BASE-POS is the position relative to which offsets should be applied." |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1131 ;; This is currently called in 3 cases: |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1132 ;; - :before opener, where rest=nil but base-pos could as well be parent. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1133 ;; - :before other, where |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1134 ;; ; after=nil |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1135 ;; ; parent is set |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1136 ;; ; base-pos=parent |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1137 ;; - :after tok, where |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1138 ;; ; after is set; parent=nil; base-pos=point; |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1139 (save-excursion |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1140 (let ((offset |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1141 (let ((smie--parent parent) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1142 (smie--token token) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1143 (smie--after after)) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1144 (funcall smie-rules-function method token)))) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1145 (cond |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1146 ((not offset) nil) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1147 ((eq (car-safe offset) 'column) (cdr offset)) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1148 ((integerp offset) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1149 (+ offset |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1150 (if (null base-pos) 0 |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1151 (goto-char base-pos) |
111603
c901fac3b428
* lisp/emacs-lisp/smie.el (smie-rule-parent, smie-indent--rule):
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111382
diff
changeset
|
1152 ;; Use smie-indent-virtual when indenting relative to an opener: |
c901fac3b428
* lisp/emacs-lisp/smie.el (smie-rule-parent, smie-indent--rule):
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111382
diff
changeset
|
1153 ;; this will also by default use current-column unless |
c901fac3b428
* lisp/emacs-lisp/smie.el (smie-rule-parent, smie-indent--rule):
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111382
diff
changeset
|
1154 ;; that opener is hanging, but will additionally consult |
c901fac3b428
* lisp/emacs-lisp/smie.el (smie-rule-parent, smie-indent--rule):
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111382
diff
changeset
|
1155 ;; rules-function, so it gives it a chance to tweak indentation |
c901fac3b428
* lisp/emacs-lisp/smie.el (smie-rule-parent, smie-indent--rule):
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111382
diff
changeset
|
1156 ;; (e.g. by forcing indentation relative to its own parent, as in |
c901fac3b428
* lisp/emacs-lisp/smie.el (smie-rule-parent, smie-indent--rule):
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111382
diff
changeset
|
1157 ;; fn a => fn b => fn c =>). |
c901fac3b428
* lisp/emacs-lisp/smie.el (smie-rule-parent, smie-indent--rule):
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111382
diff
changeset
|
1158 ;; When parent==nil it doesn't matter because the only case |
c901fac3b428
* lisp/emacs-lisp/smie.el (smie-rule-parent, smie-indent--rule):
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111382
diff
changeset
|
1159 ;; where it's really used is when the base-pos is hanging anyway. |
c901fac3b428
* lisp/emacs-lisp/smie.el (smie-rule-parent, smie-indent--rule):
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111382
diff
changeset
|
1160 (if (or (and parent (null (car parent))) |
c901fac3b428
* lisp/emacs-lisp/smie.el (smie-rule-parent, smie-indent--rule):
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111382
diff
changeset
|
1161 (smie-indent--hanging-p)) |
111382
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1162 (smie-indent-virtual) (current-column))))) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1163 (t (error "Unknown indentation offset %s" offset)))))) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1164 |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1165 (defun smie-indent-forward-token () |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1166 "Skip token forward and return it, along with its levels." |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1167 (let ((tok (funcall smie-forward-token-function))) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1168 (cond |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1169 ((< 0 (length tok)) (assoc tok smie-grammar)) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1170 ((looking-at "\\s(\\|\\s)\\(\\)") |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1171 (forward-char 1) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1172 (cons (buffer-substring (1- (point)) (point)) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1173 (if (match-end 1) '(0 nil) '(nil 0))))))) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1174 |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1175 (defun smie-indent-backward-token () |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1176 "Skip token backward and return it, along with its levels." |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1177 (let ((tok (funcall smie-backward-token-function)) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1178 class) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1179 (cond |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1180 ((< 0 (length tok)) (assoc tok smie-grammar)) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1181 ;; 4 == open paren syntax, 5 == close. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1182 ((memq (setq class (syntax-class (syntax-after (1- (point))))) '(4 5)) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1183 (forward-char -1) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1184 (cons (buffer-substring (point) (1+ (point))) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1185 (if (eq class 4) '(nil 0) '(0 nil))))))) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1186 |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1187 (defun smie-indent-virtual () |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1188 ;; We used to take an optional arg (with value :not-hanging) to specify that |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1189 ;; we should only use (smie-indent-calculate) if we're looking at a hanging |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1190 ;; keyword. This was a bad idea, because the virtual indent of a position |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1191 ;; should not depend on the caller, since it leads to situations where two |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1192 ;; dependent indentations get indented differently. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1193 "Compute the virtual indentation to use for point. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1194 This is used when we're not trying to indent point but just |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1195 need to compute the column at which point should be indented |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1196 in order to figure out the indentation of some other (further down) point." |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1197 ;; Trust pre-existing indentation on other lines. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1198 (if (smie-indent--bolp) (current-column) (smie-indent-calculate))) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1199 |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1200 (defun smie-indent-fixindent () |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1201 ;; Obey the `fixindent' special comment. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1202 (and (smie-indent--bolp) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1203 (save-excursion |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1204 (comment-normalize-vars) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1205 (re-search-forward (concat comment-start-skip |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1206 "fixindent" |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1207 comment-end-skip) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1208 ;; 1+ to account for the \n comment termination. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1209 (1+ (line-end-position)) t)) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1210 (current-column))) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1211 |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1212 (defun smie-indent-bob () |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1213 ;; Start the file at column 0. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1214 (save-excursion |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1215 (forward-comment (- (point))) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1216 (if (bobp) 0))) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1217 |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1218 (defun smie-indent-close () |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1219 ;; Align close paren with opening paren. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1220 (save-excursion |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1221 ;; (forward-comment (point-max)) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1222 (when (looking-at "\\s)") |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1223 (while (not (zerop (skip-syntax-forward ")"))) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1224 (skip-chars-forward " \t")) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1225 (condition-case nil |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1226 (progn |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1227 (backward-sexp 1) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1228 (smie-indent-virtual)) ;:not-hanging |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1229 (scan-error nil))))) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1230 |
111775
81cac26277b0
* emacs-lisp/smie.el (smie-prec2->grammar): Simplify handling
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111622
diff
changeset
|
1231 (defun smie-indent-keyword (&optional token) |
81cac26277b0
* emacs-lisp/smie.el (smie-prec2->grammar): Simplify handling
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111622
diff
changeset
|
1232 "Indent point based on the token that follows it immediately. |
81cac26277b0
* emacs-lisp/smie.el (smie-prec2->grammar): Simplify handling
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111622
diff
changeset
|
1233 If TOKEN is non-nil, assume that that is the token that follows point. |
81cac26277b0
* emacs-lisp/smie.el (smie-prec2->grammar): Simplify handling
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111622
diff
changeset
|
1234 Returns either a column number or nil if it considers that indentation |
81cac26277b0
* emacs-lisp/smie.el (smie-prec2->grammar): Simplify handling
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111622
diff
changeset
|
1235 should not be computed on the basis of the following token." |
111382
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1236 (save-excursion |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1237 (let* ((pos (point)) |
111775
81cac26277b0
* emacs-lisp/smie.el (smie-prec2->grammar): Simplify handling
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111622
diff
changeset
|
1238 (toklevels |
81cac26277b0
* emacs-lisp/smie.el (smie-prec2->grammar): Simplify handling
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111622
diff
changeset
|
1239 (if token |
81cac26277b0
* emacs-lisp/smie.el (smie-prec2->grammar): Simplify handling
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111622
diff
changeset
|
1240 (assoc token smie-grammar) |
81cac26277b0
* emacs-lisp/smie.el (smie-prec2->grammar): Simplify handling
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111622
diff
changeset
|
1241 (let* ((res (smie-indent-forward-token))) |
81cac26277b0
* emacs-lisp/smie.el (smie-prec2->grammar): Simplify handling
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111622
diff
changeset
|
1242 ;; Ignore tokens on subsequent lines. |
81cac26277b0
* emacs-lisp/smie.el (smie-prec2->grammar): Simplify handling
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111622
diff
changeset
|
1243 (if (and (< pos (line-beginning-position)) |
81cac26277b0
* emacs-lisp/smie.el (smie-prec2->grammar): Simplify handling
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111622
diff
changeset
|
1244 ;; Make sure `token' also *starts* on another line. |
81cac26277b0
* emacs-lisp/smie.el (smie-prec2->grammar): Simplify handling
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111622
diff
changeset
|
1245 (save-excursion |
81cac26277b0
* emacs-lisp/smie.el (smie-prec2->grammar): Simplify handling
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111622
diff
changeset
|
1246 (smie-indent-backward-token) |
81cac26277b0
* emacs-lisp/smie.el (smie-prec2->grammar): Simplify handling
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111622
diff
changeset
|
1247 (< pos (line-beginning-position)))) |
81cac26277b0
* emacs-lisp/smie.el (smie-prec2->grammar): Simplify handling
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111622
diff
changeset
|
1248 nil |
81cac26277b0
* emacs-lisp/smie.el (smie-prec2->grammar): Simplify handling
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111622
diff
changeset
|
1249 (goto-char pos) |
81cac26277b0
* emacs-lisp/smie.el (smie-prec2->grammar): Simplify handling
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111622
diff
changeset
|
1250 res))))) |
81cac26277b0
* emacs-lisp/smie.el (smie-prec2->grammar): Simplify handling
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111622
diff
changeset
|
1251 (setq token (pop toklevels)) |
111622
df422e3ae879
* emacs-lisp/smie.el (smie-bnf-classify): Signal errors for tokens
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111605
diff
changeset
|
1252 (cond |
111775
81cac26277b0
* emacs-lisp/smie.el (smie-prec2->grammar): Simplify handling
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111622
diff
changeset
|
1253 ((null (cdr toklevels)) nil) ;Not a keyword. |
111622
df422e3ae879
* emacs-lisp/smie.el (smie-bnf-classify): Signal errors for tokens
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111605
diff
changeset
|
1254 ((not (numberp (car toklevels))) |
111775
81cac26277b0
* emacs-lisp/smie.el (smie-prec2->grammar): Simplify handling
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111622
diff
changeset
|
1255 ;; Different cases: |
81cac26277b0
* emacs-lisp/smie.el (smie-prec2->grammar): Simplify handling
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111622
diff
changeset
|
1256 ;; - smie-indent--bolp: "indent according to others". |
81cac26277b0
* emacs-lisp/smie.el (smie-prec2->grammar): Simplify handling
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111622
diff
changeset
|
1257 ;; - common hanging: "indent according to others". |
81cac26277b0
* emacs-lisp/smie.el (smie-prec2->grammar): Simplify handling
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111622
diff
changeset
|
1258 ;; - SML-let hanging: "indent like parent". |
81cac26277b0
* emacs-lisp/smie.el (smie-prec2->grammar): Simplify handling
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111622
diff
changeset
|
1259 ;; - if-after-else: "indent-like parent". |
81cac26277b0
* emacs-lisp/smie.el (smie-prec2->grammar): Simplify handling
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111622
diff
changeset
|
1260 ;; - middle-of-line: "trust current position". |
81cac26277b0
* emacs-lisp/smie.el (smie-prec2->grammar): Simplify handling
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111622
diff
changeset
|
1261 (cond |
81cac26277b0
* emacs-lisp/smie.el (smie-prec2->grammar): Simplify handling
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111622
diff
changeset
|
1262 ((smie-indent--rule :before token)) |
81cac26277b0
* emacs-lisp/smie.el (smie-prec2->grammar): Simplify handling
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111622
diff
changeset
|
1263 ((smie-indent--bolp) ;I.e. non-virtual indent. |
81cac26277b0
* emacs-lisp/smie.el (smie-prec2->grammar): Simplify handling
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111622
diff
changeset
|
1264 ;; For an open-paren-like thingy at BOL, always indent only |
81cac26277b0
* emacs-lisp/smie.el (smie-prec2->grammar): Simplify handling
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111622
diff
changeset
|
1265 ;; based on other rules (typically smie-indent-after-keyword). |
81cac26277b0
* emacs-lisp/smie.el (smie-prec2->grammar): Simplify handling
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111622
diff
changeset
|
1266 nil) |
81cac26277b0
* emacs-lisp/smie.el (smie-prec2->grammar): Simplify handling
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111622
diff
changeset
|
1267 (t |
81cac26277b0
* emacs-lisp/smie.el (smie-prec2->grammar): Simplify handling
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111622
diff
changeset
|
1268 ;; By default use point unless we're hanging. |
81cac26277b0
* emacs-lisp/smie.el (smie-prec2->grammar): Simplify handling
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111622
diff
changeset
|
1269 (unless (smie-indent--hanging-p) (current-column))))) |
111622
df422e3ae879
* emacs-lisp/smie.el (smie-bnf-classify): Signal errors for tokens
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111605
diff
changeset
|
1270 (t |
111382
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1271 ;; FIXME: This still looks too much like black magic!! |
111775
81cac26277b0
* emacs-lisp/smie.el (smie-prec2->grammar): Simplify handling
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111622
diff
changeset
|
1272 (let* ((parent (smie-backward-sexp token))) |
111382
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1273 ;; Different behaviors: |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1274 ;; - align with parent. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1275 ;; - parent + offset. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1276 ;; - after parent's column + offset (actually, after or before |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1277 ;; depending on where backward-sexp stopped). |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1278 ;; ? let it drop to some other indentation function (almost never). |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1279 ;; ? parent + offset + parent's own offset. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1280 ;; Different cases: |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1281 ;; - bump into a same-level operator. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1282 ;; - bump into a specific known parent. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1283 ;; - find a matching open-paren thingy. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1284 ;; - bump into some random parent. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1285 ;; ? borderline case (almost never). |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1286 ;; ? bump immediately into a parent. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1287 (cond |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1288 ((not (or (< (point) pos) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1289 (and (cadr parent) (< (cadr parent) pos)))) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1290 ;; If we didn't move at all, that means we didn't really skip |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1291 ;; what we wanted. Should almost never happen, other than |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1292 ;; maybe when an infix or close-paren is at the beginning |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1293 ;; of a buffer. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1294 nil) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1295 ((save-excursion |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1296 (goto-char pos) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1297 (smie-indent--rule :before token nil parent (cadr parent)))) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1298 ((eq (car parent) (car toklevels)) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1299 ;; We bumped into a same-level operator; align with it. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1300 (if (and (smie-indent--bolp) (/= (point) pos) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1301 (save-excursion |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1302 (goto-char (goto-char (cadr parent))) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1303 (not (smie-indent--bolp)))) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1304 ;; If the parent is at EOL and its children are indented like |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1305 ;; itself, then we can just obey the indentation chosen for the |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1306 ;; child. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1307 ;; This is important for operators like ";" which |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1308 ;; are usually at EOL (and have an offset of 0): otherwise we'd |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1309 ;; always go back over all the statements, which is |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1310 ;; a performance problem and would also mean that fixindents |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1311 ;; in the middle of such a sequence would be ignored. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1312 ;; |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1313 ;; This is a delicate point! |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1314 ;; Even if the offset is not 0, we could follow the same logic |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1315 ;; and subtract the offset from the child's indentation. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1316 ;; But that would more often be a bad idea: OT1H we generally |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1317 ;; want to reuse the closest similar indentation point, so that |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1318 ;; the user's choice (or the fixindents) are obeyed. But OTOH |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1319 ;; we don't want this to affect "unrelated" parts of the code. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1320 ;; E.g. a fixindent in the body of a "begin..end" should not |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1321 ;; affect the indentation of the "end". |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1322 (current-column) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1323 (goto-char (cadr parent)) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1324 ;; Don't use (smie-indent-virtual :not-hanging) here, because we |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1325 ;; want to jump back over a sequence of same-level ops such as |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1326 ;; a -> b -> c |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1327 ;; -> d |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1328 ;; So as to align with the earliest appropriate place. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1329 (smie-indent-virtual))) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1330 (t |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1331 (if (and (= (point) pos) (smie-indent--bolp)) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1332 ;; Since we started at BOL, we're not computing a virtual |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1333 ;; indentation, and we're still at the starting point, so |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1334 ;; we can't use `current-column' which would cause |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1335 ;; indentation to depend on itself and we can't use |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1336 ;; smie-indent-virtual since that would be an inf-loop. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1337 nil |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1338 ;; In indent-keyword, if we're indenting `then' wrt `if', we |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1339 ;; want to use indent-virtual rather than use just |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1340 ;; current-column, so that we can apply the (:before . "if") |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1341 ;; rule which does the "else if" dance in SML. But in other |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1342 ;; cases, we do not want to use indent-virtual (e.g. indentation |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1343 ;; of "*" w.r.t "+", or ";" wrt "("). We could just always use |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1344 ;; indent-virtual and then have indent-rules say explicitly to |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1345 ;; use `point' after things like "(" or "+" when they're not at |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1346 ;; EOL, but you'd end up with lots of those rules. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1347 ;; So we use a heuristic here, which is that we only use virtual |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1348 ;; if the parent is tightly linked to the child token (they're |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1349 ;; part of the same BNF rule). |
111622
df422e3ae879
* emacs-lisp/smie.el (smie-bnf-classify): Signal errors for tokens
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111605
diff
changeset
|
1350 (if (car parent) (current-column) (smie-indent-virtual))))))))))) |
111382
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1351 |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1352 (defun smie-indent-comment () |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1353 "Compute indentation of a comment." |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1354 ;; Don't do it for virtual indentations. We should normally never be "in |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1355 ;; front of a comment" when doing virtual-indentation anyway. And if we are |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1356 ;; (as can happen in octave-mode), moving forward can lead to inf-loops. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1357 (and (smie-indent--bolp) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1358 (let ((pos (point))) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1359 (save-excursion |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1360 (beginning-of-line) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1361 (and (re-search-forward comment-start-skip (line-end-position) t) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1362 (eq pos (or (match-end 1) (match-beginning 0)))))) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1363 (save-excursion |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1364 (forward-comment (point-max)) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1365 (skip-chars-forward " \t\r\n") |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1366 (smie-indent-calculate)))) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1367 |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1368 (defun smie-indent-comment-continue () |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1369 ;; indentation of comment-continue lines. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1370 (let ((continue (and comment-continue |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1371 (comment-string-strip comment-continue t t)))) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1372 (and (< 0 (length continue)) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1373 (looking-at (regexp-quote continue)) (nth 4 (syntax-ppss)) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1374 (let ((ppss (syntax-ppss))) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1375 (save-excursion |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1376 (forward-line -1) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1377 (if (<= (point) (nth 8 ppss)) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1378 (progn (goto-char (1+ (nth 8 ppss))) (current-column)) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1379 (skip-chars-forward " \t") |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1380 (if (looking-at (regexp-quote continue)) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1381 (current-column)))))))) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1382 |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1383 (defun smie-indent-comment-close () |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1384 (and (boundp 'comment-end-skip) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1385 comment-end-skip |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1386 (not (looking-at " \t*$")) ;Not just a \n comment-closer. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1387 (looking-at comment-end-skip) |
111603
c901fac3b428
* lisp/emacs-lisp/smie.el (smie-rule-parent, smie-indent--rule):
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111382
diff
changeset
|
1388 (let ((end (match-string 0))) |
c901fac3b428
* lisp/emacs-lisp/smie.el (smie-rule-parent, smie-indent--rule):
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111382
diff
changeset
|
1389 (and (nth 4 (syntax-ppss)) |
c901fac3b428
* lisp/emacs-lisp/smie.el (smie-rule-parent, smie-indent--rule):
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111382
diff
changeset
|
1390 (save-excursion |
c901fac3b428
* lisp/emacs-lisp/smie.el (smie-rule-parent, smie-indent--rule):
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111382
diff
changeset
|
1391 (goto-char (nth 8 (syntax-ppss))) |
c901fac3b428
* lisp/emacs-lisp/smie.el (smie-rule-parent, smie-indent--rule):
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111382
diff
changeset
|
1392 (and (looking-at comment-start-skip) |
c901fac3b428
* lisp/emacs-lisp/smie.el (smie-rule-parent, smie-indent--rule):
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111382
diff
changeset
|
1393 (let ((start (match-string 0))) |
c901fac3b428
* lisp/emacs-lisp/smie.el (smie-rule-parent, smie-indent--rule):
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111382
diff
changeset
|
1394 ;; Align the common substring between starter |
c901fac3b428
* lisp/emacs-lisp/smie.el (smie-rule-parent, smie-indent--rule):
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111382
diff
changeset
|
1395 ;; and ender, if possible. |
c901fac3b428
* lisp/emacs-lisp/smie.el (smie-rule-parent, smie-indent--rule):
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111382
diff
changeset
|
1396 (if (string-match "\\(.+\\).*\n\\(.*?\\)\\1" |
c901fac3b428
* lisp/emacs-lisp/smie.el (smie-rule-parent, smie-indent--rule):
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111382
diff
changeset
|
1397 (concat start "\n" end)) |
c901fac3b428
* lisp/emacs-lisp/smie.el (smie-rule-parent, smie-indent--rule):
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111382
diff
changeset
|
1398 (+ (current-column) (match-beginning 0) |
c901fac3b428
* lisp/emacs-lisp/smie.el (smie-rule-parent, smie-indent--rule):
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111382
diff
changeset
|
1399 (- (match-beginning 2) (match-end 2))) |
c901fac3b428
* lisp/emacs-lisp/smie.el (smie-rule-parent, smie-indent--rule):
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111382
diff
changeset
|
1400 (current-column))))))))) |
111382
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1401 |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1402 (defun smie-indent-comment-inside () |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1403 (and (nth 4 (syntax-ppss)) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1404 'noindent)) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1405 |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1406 (defun smie-indent-after-keyword () |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1407 ;; Indentation right after a special keyword. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1408 (save-excursion |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1409 (let* ((pos (point)) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1410 (toklevel (smie-indent-backward-token)) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1411 (tok (car toklevel))) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1412 (cond |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1413 ((null toklevel) nil) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1414 ((smie-indent--rule :after tok pos nil (point))) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1415 ;; The default indentation after a keyword/operator is |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1416 ;; 0 for infix, t for prefix, and use another rule |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1417 ;; for postfix. |
111622
df422e3ae879
* emacs-lisp/smie.el (smie-bnf-classify): Signal errors for tokens
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111605
diff
changeset
|
1418 ((not (numberp (nth 2 toklevel))) nil) ;A closer. |
df422e3ae879
* emacs-lisp/smie.el (smie-bnf-classify): Signal errors for tokens
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111605
diff
changeset
|
1419 ((or (not (numberp (nth 1 toklevel))) ;An opener. |
df422e3ae879
* emacs-lisp/smie.el (smie-bnf-classify): Signal errors for tokens
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111605
diff
changeset
|
1420 (rassoc tok smie-closer-alist)) ;An inner. |
111382
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1421 (+ (smie-indent-virtual) (smie-indent--offset 'basic))) ; |
111622
df422e3ae879
* emacs-lisp/smie.el (smie-bnf-classify): Signal errors for tokens
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
111605
diff
changeset
|
1422 (t (smie-indent-virtual)))))) ;An infix. |
111382
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1423 |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1424 (defun smie-indent-exps () |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1425 ;; Indentation of sequences of simple expressions without |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1426 ;; intervening keywords or operators. E.g. "a b c" or "g (balbla) f". |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1427 ;; Can be a list of expressions or a function call. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1428 ;; If it's a function call, the first element is special (it's the |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1429 ;; function). We distinguish function calls from mere lists of |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1430 ;; expressions based on whether the preceding token is listed in |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1431 ;; the `list-intro' entry of smie-indent-rules. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1432 ;; |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1433 ;; TODO: to indent Lisp code, we should add a way to specify |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1434 ;; particular indentation for particular args depending on the |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1435 ;; function (which would require always skipping back until the |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1436 ;; function). |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1437 ;; TODO: to indent C code, such as "if (...) {...}" we might need |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1438 ;; to add similar indentation hooks for particular positions, but |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1439 ;; based on the preceding token rather than based on the first exp. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1440 (save-excursion |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1441 (let ((positions nil) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1442 arg) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1443 (while (and (null (car (smie-backward-sexp))) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1444 (push (point) positions) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1445 (not (smie-indent--bolp)))) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1446 (save-excursion |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1447 ;; Figure out if the atom we just skipped is an argument rather |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1448 ;; than a function. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1449 (setq arg |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1450 (or (null (car (smie-backward-sexp))) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1451 (funcall smie-rules-function :list-intro |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1452 (funcall smie-backward-token-function))))) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1453 (cond |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1454 ((null positions) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1455 ;; We're the first expression of the list. In that case, the |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1456 ;; indentation should be (have been) determined by its context. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1457 nil) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1458 (arg |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1459 ;; There's a previous element, and it's not special (it's not |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1460 ;; the function), so let's just align with that one. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1461 (goto-char (car positions)) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1462 (current-column)) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1463 ((cdr positions) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1464 ;; We skipped some args plus the function and bumped into something. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1465 ;; Align with the first arg. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1466 (goto-char (cadr positions)) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1467 (current-column)) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1468 (positions |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1469 ;; We're the first arg. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1470 (goto-char (car positions)) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1471 (+ (smie-indent--offset 'args) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1472 ;; We used to use (smie-indent-virtual), but that |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1473 ;; doesn't seem right since it might then indent args less than |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1474 ;; the function itself. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1475 (current-column))))))) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1476 |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1477 (defvar smie-indent-functions |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1478 '(smie-indent-fixindent smie-indent-bob smie-indent-close |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1479 smie-indent-comment smie-indent-comment-continue smie-indent-comment-close |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1480 smie-indent-comment-inside smie-indent-keyword smie-indent-after-keyword |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1481 smie-indent-exps) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1482 "Functions to compute the indentation. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1483 Each function is called with no argument, shouldn't move point, and should |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1484 return either nil if it has no opinion, or an integer representing the column |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1485 to which that point should be aligned, if we were to reindent it.") |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1486 |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1487 (defun smie-indent-calculate () |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1488 "Compute the indentation to use for point." |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1489 (run-hook-with-args-until-success 'smie-indent-functions)) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1490 |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1491 (defun smie-indent-line () |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1492 "Indent current line using the SMIE indentation engine." |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1493 (interactive) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1494 (let* ((savep (point)) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1495 (indent (or (with-demoted-errors |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1496 (save-excursion |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1497 (forward-line 0) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1498 (skip-chars-forward " \t") |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1499 (if (>= (point) savep) (setq savep nil)) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1500 (or (smie-indent-calculate) 0))) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1501 0))) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1502 (if (not (numberp indent)) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1503 ;; If something funny is used (e.g. `noindent'), return it. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1504 indent |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1505 (if (< indent 0) (setq indent 0)) ;Just in case. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1506 (if savep |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1507 (save-excursion (indent-line-to indent)) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1508 (indent-line-to indent))))) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1509 |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1510 (defun smie-setup (grammar rules-function &rest keywords) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1511 "Setup SMIE navigation and indentation. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1512 GRAMMAR is a grammar table generated by `smie-prec2->grammar'. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1513 RULES-FUNCTION is a set of indentation rules for use on `smie-rules-function'. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1514 KEYWORDS are additional arguments, which can use the following keywords: |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1515 - :forward-token FUN |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1516 - :backward-token FUN" |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1517 (set (make-local-variable 'smie-rules-function) rules-function) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1518 (set (make-local-variable 'smie-grammar) grammar) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1519 (set (make-local-variable 'indent-line-function) 'smie-indent-line) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1520 (set (make-local-variable 'forward-sexp-function) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1521 'smie-forward-sexp-command) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1522 (while keywords |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1523 (let ((k (pop keywords)) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1524 (v (pop keywords))) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1525 (case k |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1526 (:forward-token |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1527 (set (make-local-variable 'smie-forward-token-function) v)) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1528 (:backward-token |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1529 (set (make-local-variable 'smie-backward-token-function) v)) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1530 (t (message "smie-setup: ignoring unknown keyword %s" k))))) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1531 (let ((ca (cdr (assq :smie-closer-alist grammar)))) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1532 (when ca |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1533 (set (make-local-variable 'smie-closer-alist) ca) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1534 ;; Only needed for interactive calls to blink-matching-open. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1535 (set (make-local-variable 'blink-matching-check-function) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1536 #'smie-blink-matching-check) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1537 (add-hook 'post-self-insert-hook |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1538 #'smie-blink-matching-open 'append 'local) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1539 (set (make-local-variable 'smie-blink-matching-triggers) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1540 (append smie-blink-matching-triggers |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1541 ;; Rather than wait for SPC to blink, try to blink as |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1542 ;; soon as we type the last char of a block ender. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1543 (let ((closers (sort (mapcar #'cdr smie-closer-alist) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1544 #'string-lessp)) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1545 (triggers ()) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1546 closer) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1547 (while (setq closer (pop closers)) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1548 (unless (and closers |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1549 ;; FIXME: this eliminates prefixes of other |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1550 ;; closers, but we should probably elimnate |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1551 ;; prefixes of other keywords as well. |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1552 (string-prefix-p closer (car closers))) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1553 (push (aref closer (1- (length closer))) triggers))) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1554 (delete-dups triggers))))))) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1555 |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1556 |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1557 (provide 'smie) |
1aba3578b8d8
* lisp/emacs-lisp/smie.el: New package.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1558 ;;; smie.el ends here |