]> code.delx.au - gnu-emacs-elpa/blob - packages/ada-mode/gpr-wisi.el
remove bogus execute priv
[gnu-emacs-elpa] / packages / ada-mode / gpr-wisi.el
1 ;;; An indentation engine for gpr mode, using the wisent LALR parser
2 ;;
3 ;; [1] GNAT user guide (info "gnat_ugn")
4 ;;
5 ;; Copyright (C) 2013, 2014 Free Software Foundation, Inc.
6 ;;
7 ;; Author: Stephen Leake <stephen_leake@member.fsf.org>
8 ;;
9 ;; This file is part of GNU Emacs.
10 ;;
11 ;; GNU Emacs is free software: you can redistribute it and/or modify
12 ;; it under the terms of the GNU General Public License as published by
13 ;; the Free Software Foundation, either version 3 of the License, or
14 ;; (at your option) any later version.
15 ;;
16 ;; GNU Emacs is distributed in the hope that it will be useful,
17 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
18 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 ;; GNU General Public License for more details.
20 ;;
21 ;; You should have received a copy of the GNU General Public License
22 ;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
23 ;;
24 ;;; History: first version Jan 2013
25 ;;
26 ;;; code style
27 ;;
28 ;; I don't use 'pcase', because it gives _really_ confusing errors
29 ;; when I forget a ')' somewhere. Even worse, the error message is
30 ;; given when you use edebug on a defun, not when you eval it. This
31 ;; code is hard enough to debug!
32 ;;
33 ;;;;
34
35 ;; we reuse some stuff from ada-mode
36 (require 'ada-indent-user-options)
37 (require 'gpr-grammar-wy)
38 (require 'gpr-mode)
39 (require 'wisi)
40
41 (defconst gpr-wisi-class-list
42 '(
43 block-start
44 block-middle
45 block-end
46 close-paren
47 open-paren
48 statement-end
49 statement-other
50 statement-start
51 ))
52
53 (defun gpr-wisi-indent-cache (offset cache)
54 "Return indentation of OFFSET relative to CACHE or containing ancestor of CACHE that is at a line beginning."
55 (let ((indent (current-indentation)))
56 (while (and cache
57 (not (= (current-column) indent)))
58 (when (eq 'WHEN (wisi-cache-token cache))
59 (setq offset (+ offset ada-indent-when)))
60 (setq cache (wisi-goto-containing cache))
61 (setq indent (current-indentation)))
62 (+ (current-indentation) offset)
63 ))
64
65 (defun gpr-wisi-indent-containing (offset cache)
66 "Return indentation of OFFSET relative to containing ancestor of CACHE that is at a line beginning."
67 (gpr-wisi-indent-cache offset (wisi-goto-containing cache)))
68
69 (defun gpr-wisi-before-cache ()
70 (let ((cache (wisi-get-cache (point))))
71 (when cache
72 (cl-ecase (wisi-cache-class cache)
73 (block-start (wisi-indent-start ada-indent (wisi-backward-cache)))
74 (block-end (wisi-indent-start 0 cache))
75 (block-middle
76 (wisi-indent-start
77 (if (eq (wisi-cache-token cache) 'WHEN) ada-indent-when 0)
78 ;; FIXME (later): need test of ada-indent-when in gpr
79 cache))
80 (close-paren (wisi-indent-paren 0))
81 (open-paren nil); let after-keyword handle it
82 (statement-start
83 (if (not (wisi-get-containing-cache cache))
84 ;; at bob
85 0
86 ;; not at bob
87 (gpr-wisi-indent-containing ada-indent cache)))
88 ))
89 ))
90
91 (defun gpr-wisi-after-cache ()
92 (let ((cache (wisi-backward-cache)))
93 (if (not cache)
94 ;; bob
95 0
96 (cl-ecase (wisi-cache-class cache)
97 (block-end
98 (wisi-indent-current 0))
99
100 (block-middle
101 (cl-case (wisi-cache-token cache)
102 (WHEN
103 (gpr-wisi-indent-cache ada-indent-broken cache))
104 (t
105 (gpr-wisi-indent-cache ada-indent cache))
106 ))
107
108 (block-start
109 (cl-case (wisi-cache-token cache)
110 (EQUAL_GREATER
111 (gpr-wisi-indent-containing ada-indent cache))
112 (t
113 (gpr-wisi-indent-cache ada-indent cache))
114 ))
115
116 (open-paren
117 (1+ (current-column)))
118
119 (statement-end
120 (wisi-indent-start 0 cache))
121
122 ((statement-other close-paren)
123 ;; test/gpr/simple.gpr
124 ;; ) & Style_Checks
125 ;; & Standard_Common.Compiler'Default_Switches;
126 ;;
127 ;; for Source_Dirs use
128 ;; ("../auto",
129 (wisi-indent-start ada-indent-broken cache))
130
131 (statement-start
132 ;; test/gpr/simple.gpr
133 ;; type GNAT_Version_Type
134 ;; is ("7.0.1",
135 ;; hanging
136 (gpr-wisi-indent-cache ada-indent-broken cache))
137 ))
138 ))
139
140 (defun gpr-wisi-post-parse-fail ()
141 "For `wisi-post-parse-fail-hook'."
142 ;; keep it simple :)
143 nil)
144
145 (defun gpr-wisi-which-function ()
146 "For `gpr-which-function'."
147 (wisi-validate-cache (point))
148 (let ((cache (wisi-backward-cache)))
149 (while (and cache
150 (not (and
151 (memq (wisi-cache-nonterm cache) '(package_spec simple_project_declaration))
152 (eq (wisi-cache-class cache) 'statement-start))))
153 (setq cache (wisi-goto-containing cache)))
154 (when cache
155 (wisi-forward-token); package | project
156 (wisi-forward-token t); name
157 )))
158
159 ;;; debugging
160 (defun gpr-wisi-debug-keys ()
161 "Add debug key definitions to `gpr-mode-map'."
162 (interactive)
163 (define-key gpr-mode-map "\M-h" 'wisi-show-containing-or-previous-cache)
164 (define-key gpr-mode-map "\M-j" 'wisi-show-cache)
165 (define-key gpr-mode-map "\M-k" 'wisi-show-token)
166 )
167
168 ;;;;
169 (defun gpr-wisi-setup ()
170 "Set up a buffer for parsing Ada files with wisi."
171 (wisi-setup '(gpr-wisi-before-cache
172 gpr-wisi-after-cache)
173 'gpr-wisi-post-parse-fail
174 gpr-wisi-class-list
175 gpr-grammar-wy--keyword-table
176 gpr-grammar-wy--token-table
177 gpr-grammar-wy--parse-table)
178
179 (setq gpr-indent-statement 'wisi-indent-statement)
180 (set (make-local-variable 'comment-indent-function) 'wisi-comment-indent)
181 )
182
183 (add-hook 'gpr-mode-hook 'gpr-wisi-setup)
184
185 (setq gpr-which-function 'gpr-wisi-which-function)
186
187 (setq gpr-show-parse-error 'wisi-show-parse-error)
188
189 (provide 'gpr-wisi)
190 (provide 'gpr-indent-engine)
191
192 ;; end of file