annotate lisp/emacs-lisp/smie.el @ 108700:acad6349cba4

* password-cache.el (password-cache-remove): Fix docstring.
author Michael Albinus <michael.albinus@gmx.de>
date Wed, 19 May 2010 14:52:27 +0200
parents 79ce86edba9f
children 2f547b05b620
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
108632
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
1 ;;; smie.el --- Simple Minded Indentation Engine
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
2
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
3 ;; Copyright (C) 2010 Free Software Foundation, Inc.
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
4
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
5 ;; Author: Stefan Monnier <monnier@iro.umontreal.ca>
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
6 ;; Keywords: languages, lisp, internal, parsing, indentation
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
7
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
8 ;; This file is part of GNU Emacs.
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
9
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
10 ;; GNU Emacs is free software; you can redistribute it and/or modify
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
11 ;; it under the terms of the GNU General Public License as published by
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
12 ;; the Free Software Foundation, either version 3 of the License, or
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
13 ;; (at your option) any later version.
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
14
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
15 ;; GNU Emacs is distributed in the hope that it will be useful,
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
16 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
17 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
18 ;; GNU General Public License for more details.
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
19
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
20 ;; You should have received a copy of the GNU General Public License
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
21 ;; along with this program. If not, see <http://www.gnu.org/licenses/>.
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
22
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
23 ;;; Commentary:
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
24
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
25 ;; While working on the SML indentation code, the idea grew that maybe
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
26 ;; I could write something generic to do the same thing, and at the
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
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
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
28 ;; could look like. That idea grew stronger after working on
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
29 ;; LaTeX indentation.
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
30 ;;
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
31 ;; So at some point I decided to try it out, by writing a new
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
32 ;; indentation code for Coq while trying to keep most of the code
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
33 ;; "table driven", where only the tables are Coq-specific. The result
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
34 ;; (which was used for Beluga-mode as well) turned out to be based on
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
35 ;; something pretty close to an operator precedence parser.
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
36
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
37 ;; So here is another rewrite, this time following the actual principles of
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
38 ;; operator precedence grammars. Why OPG? Even though they're among the
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
39 ;; weakest kinds of parsers, these parsers have some very desirable properties
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
40 ;; for Emacs:
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
41 ;; - most importantly for indentation, they work equally well in either
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
42 ;; direction, so you can use them to parse backward from the indentation
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
43 ;; point to learn the syntactic context;
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
44 ;; - they work locally, so there's no need to keep a cache of
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
45 ;; the parser's state;
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
46 ;; - because of that locality, indentation also works just fine when earlier
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
47 ;; parts of the buffer are syntactically incorrect since the indentation
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
48 ;; looks at "as little as possible" of the buffer make an indentation
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
49 ;; decision.
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
50 ;; - they typically have no error handling and can't even detect a parsing
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
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
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
52 ;; error because the parser just automatically does something. Better yet,
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
53 ;; we can afford to use a sloppy grammar.
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
54
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
55 ;; The development (especially the parts building the 2D precedence
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
56 ;; tables and then computing the precedence levels from it) is largely
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
57 ;; inspired from page 187-194 of "Parsing techniques" by Dick Grune
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
58 ;; and Ceriel Jacobs (BookBody.pdf available at
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
59 ;; http://www.cs.vu.nl/~dick/PTAPG.html).
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
60 ;;
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
61 ;; OTOH we had to kill many chickens, read many coffee grounds, and practiced
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
62 ;; untold numbers of black magic spells.
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
63
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
64 ;;; Code:
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
65
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
66 (eval-when-compile (require 'cl))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
67
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
68 ;;; Building precedence level tables from BNF specs.
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
69
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
70 (defun smie-set-prec2tab (table x y val &optional override)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
71 (assert (and x y))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
72 (let* ((key (cons x y))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
73 (old (gethash key table)))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
74 (if (and old (not (eq old val)))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
75 (if (gethash key override)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
76 ;; FIXME: The override is meant to resolve ambiguities,
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
77 ;; but it also hides real conflicts. It would be great to
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
78 ;; be able to distinguish the two cases so that overrides
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
79 ;; don't hide real conflicts.
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
80 (puthash key (gethash key override) table)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
81 (display-warning 'smie (format "Conflict: %s %s/%s %s" x old val y)))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
82 (puthash key val table))))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
83
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
84 (defun smie-precs-precedence-table (precs)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
85 "Compute a 2D precedence table from a list of precedences.
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
86 PRECS should be a list, sorted by precedence (e.g. \"+\" will
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
87 come before \"*\"), of elements of the form \(left OP ...)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
88 or (right OP ...) or (nonassoc OP ...) or (assoc OP ...). All operators in
108642
66f3c521df14 * emacs-lisp/smie.el: Fix typos in docstrings.
Juanma Barranquero <lekktu@gmail.com>
parents: 108632
diff changeset
89 one of those elements share the same precedence level and associativity."
108632
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
90 (let ((prec2-table (make-hash-table :test 'equal)))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
91 (dolist (prec precs)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
92 (dolist (op (cdr prec))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
93 (let ((selfrule (cdr (assq (car prec)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
94 '((left . >) (right . <) (assoc . =))))))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
95 (when selfrule
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
96 (dolist (other-op (cdr prec))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
97 (smie-set-prec2tab prec2-table op other-op selfrule))))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
98 (let ((op1 '<) (op2 '>))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
99 (dolist (other-prec precs)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
100 (if (eq prec other-prec)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
101 (setq op1 '> op2 '<)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
102 (dolist (other-op (cdr other-prec))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
103 (smie-set-prec2tab prec2-table op other-op op2)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
104 (smie-set-prec2tab prec2-table other-op op op1)))))))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
105 prec2-table))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
106
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
107 (defun smie-merge-prec2s (tables)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
108 (if (null (cdr tables))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
109 (car tables)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
110 (let ((prec2 (make-hash-table :test 'equal)))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
111 (dolist (table tables)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
112 (maphash (lambda (k v)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
113 (smie-set-prec2tab prec2 (car k) (cdr k) v))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
114 table))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
115 prec2)))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
116
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
117 (defun smie-bnf-precedence-table (bnf &rest precs)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
118 (let ((nts (mapcar 'car bnf)) ;Non-terminals
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
119 (first-ops-table ())
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
120 (last-ops-table ())
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
121 (first-nts-table ())
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
122 (last-nts-table ())
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
123 (prec2 (make-hash-table :test 'equal))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
124 (override (smie-merge-prec2s
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
125 (mapcar 'smie-precs-precedence-table precs)))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
126 again)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
127 (dolist (rules bnf)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
128 (let ((nt (car rules))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
129 (last-ops ())
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
130 (first-ops ())
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
131 (last-nts ())
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
132 (first-nts ()))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
133 (dolist (rhs (cdr rules))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
134 (assert (consp rhs))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
135 (if (not (member (car rhs) nts))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
136 (pushnew (car rhs) first-ops)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
137 (pushnew (car rhs) first-nts)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
138 (when (consp (cdr rhs))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
139 ;; If the first is not an OP we add the second (which
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
140 ;; should be an OP if BNF is an "operator grammar").
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
141 ;; Strictly speaking, this should only be done if the
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
142 ;; first is a non-terminal which can expand to a phrase
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
143 ;; without any OP in it, but checking doesn't seem worth
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
144 ;; the trouble, and it lets the writer of the BNF
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
145 ;; be a bit more sloppy by skipping uninteresting base
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
146 ;; cases which are terminals but not OPs.
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
147 (assert (not (member (cadr rhs) nts)))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
148 (pushnew (cadr rhs) first-ops)))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
149 (let ((shr (reverse rhs)))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
150 (if (not (member (car shr) nts))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
151 (pushnew (car shr) last-ops)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
152 (pushnew (car shr) last-nts)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
153 (when (consp (cdr shr))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
154 (assert (not (member (cadr shr) nts)))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
155 (pushnew (cadr shr) last-ops)))))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
156 (push (cons nt first-ops) first-ops-table)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
157 (push (cons nt last-ops) last-ops-table)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
158 (push (cons nt first-nts) first-nts-table)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
159 (push (cons nt last-nts) last-nts-table)))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
160 ;; Compute all first-ops by propagating the initial ones we have
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
161 ;; now, according to first-nts.
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
162 (setq again t)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
163 (while (prog1 again (setq again nil))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
164 (dolist (first-nts first-nts-table)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
165 (let* ((nt (pop first-nts))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
166 (first-ops (assoc nt first-ops-table)))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
167 (dolist (first-nt first-nts)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
168 (dolist (op (cdr (assoc first-nt first-ops-table)))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
169 (unless (member op first-ops)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
170 (setq again t)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
171 (push op (cdr first-ops))))))))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
172 ;; Same thing for last-ops.
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
173 (setq again t)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
174 (while (prog1 again (setq again nil))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
175 (dolist (last-nts last-nts-table)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
176 (let* ((nt (pop last-nts))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
177 (last-ops (assoc nt last-ops-table)))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
178 (dolist (last-nt last-nts)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
179 (dolist (op (cdr (assoc last-nt last-ops-table)))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
180 (unless (member op last-ops)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
181 (setq again t)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
182 (push op (cdr last-ops))))))))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
183 ;; Now generate the 2D precedence table.
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
184 (dolist (rules bnf)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
185 (dolist (rhs (cdr rules))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
186 (while (cdr rhs)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
187 (cond
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
188 ((member (car rhs) nts)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
189 (dolist (last (cdr (assoc (car rhs) last-ops-table)))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
190 (smie-set-prec2tab prec2 last (cadr rhs) '> override)))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
191 ((member (cadr rhs) nts)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
192 (dolist (first (cdr (assoc (cadr rhs) first-ops-table)))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
193 (smie-set-prec2tab prec2 (car rhs) first '< override))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
194 (if (and (cddr rhs) (not (member (car (cddr rhs)) nts)))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
195 (smie-set-prec2tab prec2 (car rhs) (car (cddr rhs))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
196 '= override)))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
197 (t (smie-set-prec2tab prec2 (car rhs) (cadr rhs) '= override)))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
198 (setq rhs (cdr rhs)))))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
199 prec2))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
200
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
201 (defun smie-prec2-levels (prec2)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
202 "Take a 2D precedence table and turn it into an alist of precedence levels.
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
203 PREC2 is a table as returned by `smie-precs-precedence-table' or
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
204 `smie-bnf-precedence-table'."
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
205 ;; For each operator, we create two "variables" (corresponding to
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
206 ;; the left and right precedence level), which are represented by
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
207 ;; cons cells. Those are the vary cons cells that appear in the
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
208 ;; final `table'. The value of each "variable" is kept in the `car'.
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
209 (let ((table ())
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
210 (csts ())
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
211 (eqs ())
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
212 tmp x y)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
213 ;; From `prec2' we construct a list of constraints between
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
214 ;; variables (aka "precedence levels"). These can be either
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
215 ;; equality constraints (in `eqs') or `<' constraints (in `csts').
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
216 (maphash (lambda (k v)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
217 (if (setq tmp (assoc (car k) table))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
218 (setq x (cddr tmp))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
219 (setq x (cons nil nil))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
220 (push (cons (car k) (cons nil x)) table))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
221 (if (setq tmp (assoc (cdr k) table))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
222 (setq y (cdr tmp))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
223 (setq y (cons nil (cons nil nil)))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
224 (push (cons (cdr k) y) table))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
225 (ecase v
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
226 (= (push (cons x y) eqs))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
227 (< (push (cons x y) csts))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
228 (> (push (cons y x) csts))))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
229 prec2)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
230 ;; First process the equality constraints.
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
231 (let ((eqs eqs))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
232 (while eqs
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
233 (let ((from (caar eqs))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
234 (to (cdar eqs)))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
235 (setq eqs (cdr eqs))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
236 (if (eq to from)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
237 (debug) ;Can it happen?
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
238 (dolist (other-eq eqs)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
239 (if (eq from (cdr other-eq)) (setcdr other-eq to))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
240 (when (eq from (car other-eq))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
241 ;; This can happen because of `assoc' settings in precs
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
242 ;; or because of a rhs like ("op" foo "op").
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
243 (setcar other-eq to)))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
244 (dolist (cst csts)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
245 (if (eq from (cdr cst)) (setcdr cst to))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
246 (if (eq from (car cst)) (setcar cst to)))))))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
247 ;; Then eliminate trivial constraints iteratively.
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
248 (let ((i 0))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
249 (while csts
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
250 (let ((rhvs (mapcar 'cdr csts))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
251 (progress nil))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
252 (dolist (cst csts)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
253 (unless (memq (car cst) rhvs)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
254 (setq progress t)
108649
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
255 ;; We could give each var in a given iteration the same value,
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
256 ;; but we can also give them arbitrarily different values.
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
257 ;; Basically, these are vars between which there is no
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
258 ;; constraint (neither equality nor inequality), so
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
259 ;; anything will do.
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
260 ;; We give them arbitrary values, which means that we
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
261 ;; replace the "no constraint" case with either > or <
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
262 ;; but not =. The reason we do that is so as to try and
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
263 ;; distinguish associative operators (which will have
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
264 ;; left = right).
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
265 (unless (caar cst)
108632
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
266 (setcar (car cst) i)
108649
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
267 (incf i))
108632
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
268 (setq csts (delq cst csts))))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
269 (unless progress
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
270 (error "Can't resolve the precedence table to precedence levels")))
108649
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
271 (incf i 10))
108632
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
272 ;; Propagate equalities back to their source.
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
273 (dolist (eq (nreverse eqs))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
274 (assert (null (caar eq)))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
275 (setcar (car eq) (cadr eq)))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
276 ;; Finally, fill in the remaining vars (which only appeared on the
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
277 ;; right side of the < constraints).
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
278 ;; Tho leaving them at nil is not a bad choice, since it makes
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
279 ;; it clear that these don't bind at all.
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
280 ;; (dolist (x table)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
281 ;; (unless (nth 1 x) (setf (nth 1 x) i))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
282 ;; (unless (nth 2 x) (setf (nth 2 x) i)))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
283 )
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
284 table))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
285
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
286 ;;; Parsing using a precedence level table.
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
287
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
288 (defvar smie-op-levels 'unset
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
289 "List of token parsing info.
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
290 Each element is of the form (TOKEN LEFT-LEVEL RIGHT-LEVEL).
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
291 Parsing is done using an operator precedence parser.")
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
292
108649
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
293 (defalias 'smie-op-left 'car)
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
294 (defalias 'smie-op-right 'cadr)
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
295
108632
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
296 (defun smie-backward-token ()
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
297 ;; FIXME: This may be an OK default but probably needs a hook.
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
298 (buffer-substring (point)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
299 (progn (if (zerop (skip-syntax-backward "."))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
300 (skip-syntax-backward "w_'"))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
301 (point))))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
302
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
303 (defun smie-forward-token ()
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
304 ;; FIXME: This may be an OK default but probably needs a hook.
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
305 (buffer-substring (point)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
306 (progn (if (zerop (skip-syntax-forward "."))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
307 (skip-syntax-forward "w_'"))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
308 (point))))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
309
108649
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
310 (defun smie-associative-p (toklevels)
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
311 ;; in "a + b + c" we want to stop at each +, but in
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
312 ;; "if a then b else c" we don't want to stop at each keyword.
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
313 ;; To distinguish the two cases, we made smie-prec2-levels choose
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
314 ;; different levels for each part of "if a then b else c", so that
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
315 ;; by checking if the left-level is equal to the right level, we can
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
316 ;; figure out that it's an associative operator.
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
317 ;; This is not 100% foolproof, tho, since a grammar like
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
318 ;; (exp ("A" exp "C") ("A" exp "B" exp "C"))
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
319 ;; will cause "B" to have equal left and right levels, even though
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
320 ;; it is not an associative operator.
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
321 ;; A better check would be the check the actual previous operator
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
322 ;; against this one to see if it's the same, but we'd have to change
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
323 ;; `levels' to keep a stack of operators rather than only levels.
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
324 (eq (smie-op-left toklevels) (smie-op-right toklevels)))
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
325
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
326 (defun smie-next-sexp (next-token next-sexp op-forw op-back halfsexp)
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
327 "Skip over one sexp.
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
328 NEXT-TOKEN is a function of no argument that moves forward by one
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
329 token (after skipping comments if needed) and returns it.
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
330 NEXT-SEXP is a lower-level function to skip one sexp.
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
331 OP-FORW is the accessor to the forward level of the level data.
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
332 OP-BACK is the accessor to the backward level of the level data.
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
333 HALFSEXP if non-nil, means skip over a partial sexp if needed. I.e. if the
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
334 first token we see is an operator, skip over its left-hand-side argument.
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
335 Possible return values:
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
336 (FORW-LEVEL POS TOKEN): we couldn't skip TOKEN because its back-level
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
337 is too high. FORW-LEVEL is the forw-level of TOKEN,
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
338 POS is its start position in the buffer.
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
339 (t POS TOKEN): same thing when we bump on the wrong side of a paren.
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
340 (nil POS TOKEN): we skipped over a paren-like pair.
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
341 nil: we skipped over an identifier, matched parentheses, ..."
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
342 (catch 'return
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
343 (let ((levels ()))
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
344 (while
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
345 (let* ((pos (point))
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
346 (token (funcall next-token))
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
347 (toklevels (cdr (assoc token smie-op-levels))))
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
348
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
349 (cond
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
350 ((null toklevels)
108652
79ce86edba9f * emacs-lisp/smie.el (smie-next-sexp): Break inf-loop at BOB.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108649
diff changeset
351 (when (equal token "")
108649
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
352 (condition-case err
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
353 (progn (goto-char pos) (funcall next-sexp 1) nil)
108652
79ce86edba9f * emacs-lisp/smie.el (smie-next-sexp): Break inf-loop at BOB.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108649
diff changeset
354 (scan-error (throw 'return (list t (caddr err)))))
79ce86edba9f * emacs-lisp/smie.el (smie-next-sexp): Break inf-loop at BOB.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108649
diff changeset
355 (if (eq pos (point))
79ce86edba9f * emacs-lisp/smie.el (smie-next-sexp): Break inf-loop at BOB.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108649
diff changeset
356 ;; We did not move, so let's abort the loop.
79ce86edba9f * emacs-lisp/smie.el (smie-next-sexp): Break inf-loop at BOB.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108649
diff changeset
357 (throw 'return (list t (point))))))
108649
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
358 ((null (funcall op-back toklevels))
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
359 ;; A token like a paren-close.
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
360 (assert (funcall op-forw toklevels)) ;Otherwise, why mention it?
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
361 (push (funcall op-forw toklevels) levels))
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
362 (t
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
363 (while (and levels (< (funcall op-back toklevels) (car levels)))
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
364 (setq levels (cdr levels)))
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
365 (cond
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
366 ((null levels)
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
367 (if (and halfsexp (funcall op-forw toklevels))
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
368 (push (funcall op-forw toklevels) levels)
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
369 (throw 'return
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
370 (prog1 (list (or (car toklevels) t) (point) token)
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
371 (goto-char pos)))))
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
372 (t
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
373 (if (and levels (= (funcall op-back toklevels) (car levels)))
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
374 (setq levels (cdr levels)))
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
375 (cond
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
376 ((null levels)
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
377 (cond
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
378 ((null (funcall op-forw toklevels))
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
379 (throw 'return (list nil (point) token)))
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
380 ((smie-associative-p toklevels)
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
381 (throw 'return
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
382 (prog1 (list (or (car toklevels) t) (point) token)
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
383 (goto-char pos))))
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
384 ;; We just found a match to the previously pending operator
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
385 ;; but this new operator is still part of a larger RHS.
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
386 ;; E.g. we're now looking at the "then" in
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
387 ;; "if a then b else c". So we have to keep parsing the
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
388 ;; rest of the construct.
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
389 (t (push (funcall op-forw toklevels) levels))))
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
390 (t
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
391 (if (funcall op-forw toklevels)
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
392 (push (funcall op-forw toklevels) levels))))))))
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
393 levels)
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
394 (setq halfsexp nil)))))
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
395
108632
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
396 (defun smie-backward-sexp (&optional halfsexp)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
397 "Skip over one sexp.
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
398 HALFSEXP if non-nil, means skip over a partial sexp if needed. I.e. if the
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
399 first token we see is an operator, skip over its left-hand-side argument.
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
400 Possible return values:
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
401 (LEFT-LEVEL POS TOKEN): we couldn't skip TOKEN because its right-level
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
402 is too high. LEFT-LEVEL is the left-level of TOKEN,
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
403 POS is its start position in the buffer.
108642
66f3c521df14 * emacs-lisp/smie.el: Fix typos in docstrings.
Juanma Barranquero <lekktu@gmail.com>
parents: 108632
diff changeset
404 (t POS TOKEN): same thing but for an open-paren or the beginning of buffer.
108632
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
405 (nil POS TOKEN): we skipped over a paren-like pair.
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
406 nil: we skipped over an identifier, matched parentheses, ..."
108649
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
407 (smie-next-sexp
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
408 (lambda () (forward-comment (- (point-max))) (smie-backward-token))
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
409 (indirect-function 'backward-sexp)
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
410 (indirect-function 'smie-op-left)
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
411 (indirect-function 'smie-op-right)
108652
79ce86edba9f * emacs-lisp/smie.el (smie-next-sexp): Break inf-loop at BOB.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108649
diff changeset
412 halfsexp))
108632
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
413
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
414 (defun smie-forward-sexp (&optional halfsexp)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
415 "Skip over one sexp.
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
416 HALFSEXP if non-nil, means skip over a partial sexp if needed. I.e. if the
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
417 first token we see is an operator, skip over its left-hand-side argument.
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
418 Possible return values:
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
419 (RIGHT-LEVEL POS TOKEN): we couldn't skip TOKEN because its left-level
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
420 is too high. RIGHT-LEVEL is the right-level of TOKEN,
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
421 POS is its end position in the buffer.
108642
66f3c521df14 * emacs-lisp/smie.el: Fix typos in docstrings.
Juanma Barranquero <lekktu@gmail.com>
parents: 108632
diff changeset
422 (t POS TOKEN): same thing but for an open-paren or the beginning of buffer.
108632
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
423 (nil POS TOKEN): we skipped over a paren-like pair.
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
424 nil: we skipped over an identifier, matched parentheses, ..."
108649
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
425 (smie-next-sexp
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
426 (lambda () (forward-comment (point-max)) (smie-forward-token))
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
427 (indirect-function 'forward-sexp)
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
428 (indirect-function 'smie-op-right)
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
429 (indirect-function 'smie-op-left)
108652
79ce86edba9f * emacs-lisp/smie.el (smie-next-sexp): Break inf-loop at BOB.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108649
diff changeset
430 halfsexp))
108632
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
431
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
432 (defun smie-backward-sexp-command (&optional n)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
433 "Move backward through N logical elements."
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
434 (interactive "p")
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
435 (if (< n 0)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
436 (smie-forward-sexp-command (- n))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
437 (let ((forward-sexp-function nil))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
438 (while (> n 0)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
439 (decf n)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
440 (let ((pos (point))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
441 (res (smie-backward-sexp 'halfsexp)))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
442 (if (and (car res) (= pos (point)) (not (bolp)))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
443 (signal 'scan-error
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
444 (list "Containing expression ends prematurely"
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
445 (cadr res) (cadr res)))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
446 nil))))))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
447
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
448 (defun smie-forward-sexp-command (&optional n)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
449 "Move forward through N logical elements."
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
450 (interactive "p")
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
451 (if (< n 0)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
452 (smie-backward-sexp-command (- n))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
453 (let ((forward-sexp-function nil))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
454 (while (> n 0)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
455 (decf n)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
456 (let ((pos (point))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
457 (res (smie-forward-sexp 'halfsexp)))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
458 (if (and (car res) (= pos (point)) (not (bolp)))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
459 (signal 'scan-error
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
460 (list "Containing expression ends prematurely"
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
461 (cadr res) (cadr res)))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
462 nil))))))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
463
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
464 ;;; The indentation engine.
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
465
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
466 (defcustom smie-indent-basic 4
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
467 "Basic amount of indentation."
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
468 :type 'integer)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
469
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
470 (defvar smie-indent-rules 'unset
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
471 "Rules of the following form.
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
472 \(TOK OFFSET) how to indent right after TOK.
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
473 \(TOK O1 O2) how to indent right after TOK:
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
474 O1 is the default;
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
475 O2 is used if TOK is \"hanging\".
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
476 \((T1 . T2) . OFFSET) how to indent token T2 w.r.t T1.
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
477 \((t . TOK) . OFFSET) how to indent TOK with respect to its parent.
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
478 \(list-intro . TOKENS) declare TOKENS as being followed by what may look like
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
479 a funcall but is just a sequence of expressions.
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
480 \(t . OFFSET) basic indentation step.
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
481 \(args . OFFSET) indentation of arguments.
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
482 A nil offset defaults to `smie-indent-basic'.")
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
483
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
484 (defun smie-indent-hanging-p ()
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
485 ;; A Hanging keyword is one that's at the end of a line except it's not at
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
486 ;; the beginning of a line.
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
487 (and (save-excursion (smie-forward-token)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
488 (skip-chars-forward " \t") (eolp))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
489 (save-excursion (skip-chars-backward " \t") (not (bolp)))))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
490
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
491 (defun smie-bolp ()
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
492 (save-excursion (skip-chars-backward " \t") (bolp)))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
493
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
494 (defun smie-indent-offset (elem)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
495 (or (cdr (assq elem smie-indent-rules))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
496 (cdr (assq t smie-indent-rules))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
497 smie-indent-basic))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
498
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
499 (defun smie-indent-calculate (&optional virtual)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
500 "Compute the indentation to use for point.
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
501 If VIRTUAL is non-nil, it means we're not trying to indent point but just
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
502 need to compute the column at which point should be indented
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
503 in order to figure out the indentation of some other (further down) point.
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
504 VIRTUAL can take two different non-nil values:
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
505 - :bolp: means that the current indentation of point can be trusted
108642
66f3c521df14 * emacs-lisp/smie.el: Fix typos in docstrings.
Juanma Barranquero <lekktu@gmail.com>
parents: 108632
diff changeset
506 to be good only if it follows a line break.
108632
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
507 - :hanging: means that the current indentation of point can be
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
508 trusted to be good except if the following token is hanging."
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
509 ;; FIXME: This has accumulated a lot of rules, some of which aren't
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
510 ;; clearly orthogonal any more, so we should probably try and
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
511 ;; restructure it somewhat.
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
512 (or
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
513 ;; Trust pre-existing indentation on other lines.
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
514 (and virtual
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
515 (if (eq virtual :hanging) (not (smie-indent-hanging-p)) (smie-bolp))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
516 (current-column))
108652
79ce86edba9f * emacs-lisp/smie.el (smie-next-sexp): Break inf-loop at BOB.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108649
diff changeset
517 ;; Start the file at column 0.
79ce86edba9f * emacs-lisp/smie.el (smie-next-sexp): Break inf-loop at BOB.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108649
diff changeset
518 (save-excursion
79ce86edba9f * emacs-lisp/smie.el (smie-next-sexp): Break inf-loop at BOB.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108649
diff changeset
519 (forward-comment (- (point-max)))
79ce86edba9f * emacs-lisp/smie.el (smie-next-sexp): Break inf-loop at BOB.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108649
diff changeset
520 (if (bobp) 0))
108632
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
521 ;; Align close paren with opening paren.
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
522 (save-excursion
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
523 ;; (forward-comment (point-max))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
524 (when (looking-at "\\s)")
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
525 (while (not (zerop (skip-syntax-forward ")")))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
526 (skip-chars-forward " \t"))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
527 (condition-case nil
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
528 (progn
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
529 (backward-sexp 1)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
530 (smie-indent-calculate :hanging))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
531 (scan-error nil))))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
532 ;; Align closing token with the corresponding opening one.
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
533 ;; (e.g. "of" with "case", or "in" with "let").
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
534 (save-excursion
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
535 (let* ((pos (point))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
536 (token (smie-forward-token))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
537 (toklevels (cdr (assoc token smie-op-levels))))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
538 (when (car toklevels)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
539 (let ((res (smie-backward-sexp 'halfsexp)) tmp)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
540 ;; If we didn't move at all, that means we didn't really skip
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
541 ;; what we wanted.
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
542 (when (< (point) pos)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
543 (cond
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
544 ((eq (car res) (car toklevels))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
545 ;; We bumped into a same-level operator. align with it.
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
546 (goto-char (cadr res))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
547 ;; Don't use (smie-indent-calculate :hanging) here, because we
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
548 ;; want to jump back over a sequence of same-level ops such as
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
549 ;; a -> b -> c
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
550 ;; -> d
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
551 ;; So as to align with the earliest appropriate place.
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
552 (smie-indent-calculate :bolp))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
553 ((equal token (save-excursion
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
554 (forward-comment (- (point-max)))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
555 (smie-backward-token)))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
556 ;; in cases such as "fn x => fn y => fn z =>",
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
557 ;; jump back to the very first fn.
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
558 ;; FIXME: should we only do that for special tokens like "=>"?
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
559 (smie-indent-calculate :bolp))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
560 ((setq tmp (assoc (cons (caddr res) token)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
561 smie-indent-rules))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
562 (goto-char (cadr res))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
563 (+ (cdr tmp) (smie-indent-calculate :hanging)))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
564 (t
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
565 (+ (or (cdr (assoc (cons t token) smie-indent-rules)) 0)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
566 (current-column)))))))))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
567 ;; Indentation of a comment.
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
568 (and (looking-at comment-start-skip)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
569 (save-excursion
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
570 (forward-comment (point-max))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
571 (skip-chars-forward " \t\r\n")
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
572 (smie-indent-calculate nil)))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
573 ;; Indentation inside a comment.
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
574 (and (looking-at "\\*") (nth 4 (syntax-ppss))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
575 (let ((ppss (syntax-ppss)))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
576 (save-excursion
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
577 (forward-line -1)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
578 (if (<= (point) (nth 8 ppss))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
579 (progn (goto-char (1+ (nth 8 ppss))) (current-column))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
580 (skip-chars-forward " \t")
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
581 (if (looking-at "\\*")
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
582 (current-column))))))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
583 ;; Indentation right after a special keyword.
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
584 (save-excursion
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
585 (let* ((tok (progn (forward-comment (- (point-max)))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
586 (smie-backward-token)))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
587 (tokinfo (assoc tok smie-indent-rules))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
588 (toklevel (assoc tok smie-op-levels)))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
589 (when (or tokinfo (and toklevel (null (cadr toklevel))))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
590 (if (or (smie-indent-hanging-p)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
591 ;; If calculating the virtual indentation point, prefer
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
592 ;; looking up the virtual indentation of the alignment
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
593 ;; point as well. This is used for indentation after
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
594 ;; "fn x => fn y =>".
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
595 virtual)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
596 (+ (smie-indent-calculate :bolp)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
597 (or (caddr tokinfo) (cadr tokinfo) (smie-indent-offset t)))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
598 (+ (current-column)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
599 (or (cadr tokinfo) (smie-indent-offset t)))))))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
600 ;; Main loop (FIXME: whatever that means!?).
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
601 (save-excursion
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
602 (let ((positions nil)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
603 (begline nil)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
604 arg)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
605 (while (and (null (car (smie-backward-sexp)))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
606 (push (point) positions)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
607 (not (setq begline (smie-bolp)))))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
608 (save-excursion
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
609 ;; Figure out if the atom we just skipped is an argument rather
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
610 ;; than a function.
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
611 (setq arg (or (null (car (smie-backward-sexp)))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
612 (member (progn (forward-comment (- (point-max)))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
613 (smie-backward-token))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
614 (cdr (assoc 'list-intro smie-indent-rules))))))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
615 (cond
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
616 ((and arg positions)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
617 (goto-char (car positions))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
618 (current-column))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
619 ((and (null begline) (cdr positions))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
620 ;; We skipped some args plus the function and bumped into something.
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
621 ;; Align with the first arg.
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
622 (goto-char (cadr positions))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
623 (current-column))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
624 ((and (null begline) positions)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
625 ;; We're the first arg.
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
626 ;; FIXME: it might not be a funcall, in which case we might be the
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
627 ;; second element.
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
628 (goto-char (car positions))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
629 (+ (smie-indent-offset 'args)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
630 ;; We used to use (smie-indent-calculate :bolp), but that
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
631 ;; doesn't seem right since it might then indent args less than
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
632 ;; the function itself.
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
633 (current-column)))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
634 ((and (null arg) (null positions))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
635 ;; We're the function itself. Not sure what to do here yet.
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
636 (if virtual (current-column)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
637 (save-excursion
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
638 (let* ((pos (point))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
639 (tok (progn (forward-comment (- (point-max)))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
640 (smie-backward-token)))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
641 (toklevels (cdr (assoc tok smie-op-levels))))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
642 (cond
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
643 ((numberp (car toklevels))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
644 ;; We're right after an infix token. Let's skip over the
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
645 ;; lefthand side.
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
646 (goto-char pos)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
647 (let (res)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
648 (while (progn (setq res (smie-backward-sexp 'halfsexp))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
649 (and (not (smie-bolp))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
650 (equal (car res) (car toklevels)))))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
651 ;; We should be right after a token of equal or
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
652 ;; higher precedence.
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
653 (cond
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
654 ((and (consp res) (memq (car res) '(t nil)))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
655 ;; The token of higher-precedence is like an open-paren.
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
656 ;; Sample case for t: foo { bar, \n[TAB] baz }.
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
657 ;; Sample case for nil: match ... with \n[TAB] | toto ...
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
658 ;; (goto-char (cadr res))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
659 (smie-indent-calculate :hanging))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
660 ((and (consp res) (<= (car res) (car toklevels)))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
661 ;; We stopped at a token of equal or higher precedence
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
662 ;; because we found a place with which to align.
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
663 (current-column))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
664 )))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
665 ;; For other cases.... hmm... we'll see when we get there.
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
666 )))))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
667 ((null positions)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
668 (smie-backward-token)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
669 (+ (smie-indent-offset 'args) (smie-indent-calculate :bolp)))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
670 ((car (smie-backward-sexp))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
671 ;; No arg stands on its own line, but the function does:
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
672 (if (cdr positions)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
673 (progn
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
674 (goto-char (cadr positions))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
675 (current-column))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
676 (goto-char (car positions))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
677 (+ (current-column) (smie-indent-offset 'args))))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
678 (t
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
679 ;; We've skipped to a previous arg on its own line: align.
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
680 (goto-char (car positions))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
681 (current-column)))))))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
682
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
683 (defun smie-indent-line ()
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
684 "Indent current line using the SMIE indentation engine."
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
685 (interactive)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
686 (let* ((savep (point))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
687 (indent (condition-case nil
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
688 (save-excursion
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
689 (forward-line 0)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
690 (skip-chars-forward " \t")
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
691 (if (>= (point) savep) (setq savep nil))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
692 (or (smie-indent-calculate) 0))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
693 (error 0))))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
694 (if (not (numberp indent))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
695 ;; If something funny is used (e.g. `noindent'), return it.
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
696 indent
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
697 (if (< indent 0) (setq indent 0)) ;Just in case.
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
698 (if savep
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
699 (save-excursion (indent-line-to indent))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
700 (indent-line-to indent)))))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
701
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
702 ;;;###autoload
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
703 (defun smie-setup (op-levels indent-rules)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
704 (set (make-local-variable 'smie-indent-rules) indent-rules)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
705 (set (make-local-variable 'smie-op-levels) op-levels)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
706 (set (make-local-variable 'indent-line-function) 'smie-indent-line))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
707
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
708
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
709 (provide 'smie)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
710 ;;; smie.el ends here