aboutsummaryrefslogtreecommitdiffhomepage
path: root/generic/proof-syntax.el
blob: 777d385855198d3c335d33aba2fb91c6a107db8a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
;;; proof-syntax.el --- Functions for dealing with syntax

;; This file is part of Proof General.

;; Portions © Copyright 1994-2012  David Aspinall and University of Edinburgh
;; Portions © Copyright 2003-2018  Free Software Foundation, Inc.
;; Portions © Copyright 2001-2017  Pierre Courtieu
;; Portions © Copyright 2010, 2016  Erik Martin-Dorel
;; Portions © Copyright 2011-2013, 2016-2017  Hendrik Tews
;; Portions © Copyright 2015-2017  Clément Pit-Claudel

;; Authors:   David Aspinall, Healfdene Goguen,
;;	      Thomas Kleymann, Dilip Sequiera

;; License:   GPL (GNU GENERAL PUBLIC LICENSE)

;;; Commentary:
;; 

;;; Code:
(require 'font-lock)
(require 'proof-config)			; proof-case-fold-search
(require 'pg-pamacs)			; proof-ass-sym

(defsubst proof-ids-to-regexp (l)
  "Maps a non-empty list of tokens L to a regexp matching any element.
Uses a regexp of the form \\_<...\\_>."
  (concat "\\_<\\(?:"
	  (regexp-opt l) ; was: (mapconcat 'identity l "\\|")
	  "\\)\\_>"))

(defsubst proof-anchor-regexp (e)
  "Anchor (\\`) and group the regexp E."
  (concat "\\`\\(" e "\\)"))

(defconst proof-no-regexp "\\<\\>"
  "A regular expression that never matches anything.")

(defsubst proof-regexp-alt-list (args)
  "Return the regexp which matches any of the regexps ARGS."
  (mapconcat #'identity args "\\|"))

(defsubst proof-regexp-alt (&rest args)
  "Return the regexp which matches any of the regexps ARGS."
  ;; see regexp-opt (NB: but that is for strings, not regexps)
  (proof-regexp-alt-list args))

(defsubst proof-re-search-forward-region (startre endre)
  "Search for a region delimited by regexps STARTRE and ENDRE.
Return the start position of the match for STARTRE, or
nil if a region cannot be found."
  (if (re-search-forward startre nil t)
      (let ((start (match-beginning 0)))
	(if (re-search-forward endre nil t)
	    start))))

;; Functions for string matching and searching that take into account
;; value of proof-case-fold-search.  Last arg to string-match is not
;; applicable.

(defsubst proof-search-forward (string &optional bound noerror count)
  "Like ‘search-forward’, but set ‘case-fold-search’ to ‘proof-case-fold-search’."
  (let
      ((case-fold-search proof-case-fold-search))
    (search-forward string bound noerror count)))

;;;###autoload
(defun proof-replace-regexp-in-string (regexp rep string)
  "Like ‘replace-regexp-in-string’, but set ‘case-fold-search’ to ‘proof-case-fold-search’."
  (let ((case-fold-search proof-case-fold-search))
    (replace-regexp-in-string regexp rep string)))

(defsubst proof-re-search-forward (regexp &optional bound noerror count)
  "Like ‘re-search-forward’, but set ‘case-fold-search’ to ‘proof-case-fold-search’."
  (let ((case-fold-search proof-case-fold-search))
    (re-search-forward regexp bound noerror count)))

(defsubst proof-re-search-backward (regexp &optional bound noerror count)
  "Like ‘re-search-backward’, but set ‘case-fold-search’ to ‘proof-case-fold-search’."
  (let ((case-fold-search proof-case-fold-search))
    (re-search-backward regexp bound noerror count)))

(defsubst proof-re-search-forward-safe (regexp &optional bound noerror count)
  "Like ‘re-search-forward’, but set ‘case-fold-search’ to ‘proof-case-fold-search’."
  (and regexp
       (let ((case-fold-search proof-case-fold-search))
	 (re-search-forward regexp bound noerror count))))

(defsubst proof-string-match (regexp string &optional start)
  "Like ‘string-match’, but set ‘case-fold-search’ to ‘proof-case-fold-search’."
  (let ((case-fold-search proof-case-fold-search))
    (string-match regexp string start)))

(defsubst proof-string-match-safe (regexp string &optional start)
  "Like ‘string-match’, but return nil if REGEXP or STRING is nil."
  (if (and regexp string) (proof-string-match regexp string start)))

(defsubst proof-stringfn-match (regexp-or-fn string)
  "Like ‘proof-string-match’ if first arg is regexp, otherwise call it."
  (cond ((stringp regexp-or-fn)
	 (proof-string-match regexp-or-fn string))
	((functionp regexp-or-fn)
	 (funcall regexp-or-fn string))))

(defsubst proof-looking-at (regexp)
  "Like ‘looking-at’, but set ‘case-fold-search’ to ‘proof-case-fold-search’."
  (let ((case-fold-search proof-case-fold-search))
    (looking-at regexp)))

(defsubst proof-looking-at-safe (regexp)
  "Like ‘proof-looking-at’, but return nil if REGEXP is nil."
  (if regexp (proof-looking-at regexp)))

;;
;; Syntactic context
;;

;; A function named after one in XEmacs
(defun proof-buffer-syntactic-context (&optional buffer)
  "Return the syntactic context of BUFFER at point.
If BUFFER is nil or omitted, the current buffer is assumed.
The returned value is one of the following symbols:

	nil		; meaning no special interpretation
	string		; meaning point is within a string
	comment		; meaning point is within a line comment"
  (save-excursion
    (if buffer (set-buffer buffer))
    (let ((pp (syntax-ppss)))
	   ;;(parse-partial-sexp (point-min) (point))))
      (cond
       ((nth 3 pp) 'string)
       ;; ((nth 7 pp) 'block-comment)
       ;; "Stefan Monnier" <monnier+misc/news@rum.cs.yale.edu> suggests
       ;; distinguishing between block comments and ordinary comments
       ;; is problematic: not what XEmacs claims and different to what
       ;; (nth 7 pp) tells us in GNU Emacs.
       ((nth 4 pp) 'comment)))))

(defsubst proof-looking-at-syntactic-context-default ()
  "Default function for `proof-looking-at-syntactic-context'."
  (or
   (proof-buffer-syntactic-context)
   (save-match-data
     (when (proof-looking-at-safe proof-script-comment-start-regexp) 'comment))
   (save-match-data
     (when (proof-looking-at-safe proof-string-start-regexp) 'string))))

(defun proof-looking-at-syntactic-context ()
  "Determine if current point is at beginning or within comment/string context.
If so, return a symbol indicating this ('comment or 'string).
This function invokes <PA-syntactic-context> if that is defined, otherwise
it calls `proof-looking-at-syntactic-context'."
  (if (fboundp (proof-ass-sym syntactic-context))
      (funcall (proof-ass-sym syntactic-context))
    (proof-looking-at-syntactic-context-default)))

(defun proof-inside-comment (pos)
  "Return non-nil if POS is inside a comment."
  (save-excursion
    (goto-char pos)
    (eq (proof-buffer-syntactic-context) 'comment)))

(defun proof-inside-string (pos)
  "Return non-nil if POS is inside a comment."
  (save-excursion
    (goto-char pos)
    (eq (proof-buffer-syntactic-context) 'string)))

;;
;; Replacing matches
;;

(defsubst proof-replace-string (string to-string)
  "Non-interactive `replace-string', using `proof-case-fold-search'."
  (while (proof-search-forward string nil t)
    (replace-match to-string nil t)))

(defsubst proof-replace-regexp (regexp to-string)
  "Non-interactive `replace-regexp', using `proof-case-fold-search'."
  (while (proof-re-search-forward regexp nil t)
    (replace-match to-string nil nil)))

(defsubst proof-replace-regexp-nocasefold (regexp to-string)
  "Non-interactive `replace-regexp', forcing `case-fold-search' to nil."
  (let ((case-fold-search nil))
    (while (proof-re-search-forward regexp nil t)
      (replace-match to-string nil nil))))

;;
;; Generic font-lock
;;

(defvar proof-id "\\(\\w\\(\\w\\|\\s_\\)*\\)"
  "A regular expression for parsing identifiers.")

;; For font-lock, we treat ,-separated identifiers as one identifier
;; and refontify commata using \{proof-zap-commas}.

(defun proof-zap-commas (limit)
  "Remove the face of all `,' from point to LIMIT.
Meant to be used from `font-lock-keywords' as a way
to unfontify commas in declarations and definitions.
Useful for provers which have declarations of the form x,y,z:Ty
All that can be said for it is that the previous ways of doing
this were even more bogus...."
(while (proof-search-forward "," limit t)
    (if (memq (get-text-property (1- (point)) 'face)
	      '(proof-declaration-name-face
		font-lock-variable-name-face
		font-lock-function-name-face))
	(put-text-property (1- (point)) (point) 'face nil))))


;;
;; Font lock: providing an alternative syntactic fontify
;; region function.
;; 
;; The hook font-lock-fontify-region-function is tempting but not
;; really a convenient place.  We just want to replace the syntactic
;; fontification function.
;;

;; (defadvice font-lock-fontify-keywords-region
;;   (before font-lock-fontify-keywords-advice (beg end &optional loudly))
;;   "Call proof assistant specific syntactic region fontify.
;; If it's bound, we call <PA>-font-lock-fontify-syntactically-region."
;;   (when (and proof-buffer-type
;; 	     (fboundp (proof-ass-sym font-lock-fontify-syntactically-region)))
;;     (funcall (proof-ass-sym font-lock-fontify-syntactically-region)
;; 	     beg end loudly)))
;; (ad-activate 'font-lock-fontify-keywords-region)

;;
;; Functions for doing something like "format" but with customizable
;; control characters.
;;

;;;###autoload
(defun proof-format (alist string)
  "Format a string by matching regexps in ALIST against STRING.
ALIST contains (REGEXP . REPLACEMENT) pairs where REPLACEMENT
may be a string or sexp evaluated to get a string."
  (while alist
    (let ((idx 0))
      (while (string-match (car (car alist)) string idx)
	(setq string
	      (concat (substring string 0 (match-beginning 0))
		      (cond
		       ((stringp (cdr (car alist)))
			(cdr (car alist)))
		       (t
			(eval (cdr (car alist)))))
		      (substring string (match-end 0))))
	(setq idx (+ (match-beginning 0) (length (cdr (car alist)))))))
    (setq alist (cdr alist)))
  string)

(defun proof-format-filename (string filename)
  "Format STRING by replacing quoted chars by escaped version of FILENAME.

%e uses the canonicalized expanded version of filename (including
directory, using `default-directory' -- see `expand-file-name').

%r uses the unadjusted (possibly relative) version of FILENAME.

%m ('module') uses the basename of the file, without directory
or extension.

%s means the same as %e.

Using %e can avoid problems with dumb proof assistants who don't
understand ~, for example.

For all these cases, the escapes in `proof-shell-filename-escapes'
are processed.

If STRING is in fact a function, instead invoke it on FILENAME and
return the resulting (string) value."
  (cond
   ((functionp string)
    (funcall string filename))
   (t
    (proof-format
     (list (cons "%s" (proof-format proof-shell-filename-escapes
				    (expand-file-name filename)))
	   (cons "%e" (proof-format proof-shell-filename-escapes
				    (expand-file-name filename)))
	   (cons "%r" (proof-format proof-shell-filename-escapes
				    filename))
	   (cons "%m" (proof-format proof-shell-filename-escapes
				    (file-name-nondirectory
				     (file-name-sans-extension filename)))))
     string))))


;;
;; Functions for inserting text into buffer.
;;

; Taken from Isamode
;
;  %l  - insert the value of isa-logic-name
;  %s  - insert the value returned by isa-current-subgoal

(defun proof-insert (text)
  "Insert TEXT into the current buffer.
TEXT may include these special characters:
  %p  - place the point here after input
Any other %-prefixed character inserts itself."
  ; would be quite nice to have this function:
  ;(isa-delete-pending-input)
  (let ((i 0) pos acc)
    (while (< i (length text))
      (let ((ch (elt text i)))
	(if (not (eq ch ?%))
	    (setq acc (concat acc (char-to-string ch)))
	  (setq i (1+ i))
	  (setq ch (elt text i))
	  (cond ;((eq ch ?l)
		; (setq acc (concat acc isa-logic-name)))
		;((eq ch ?s)
		; (setq acc
		;       (concat acc
		;	       (int-to-string
		;		(if (boundp 'isa-denoted-subgoal)
		;		    isa-denoted-subgoal
		;		  1)))))
		;((eq ch ?n)
		; (if acc (insert acc))
		; (setq acc nil)
		; (scomint-send-input))
		((eq ch ?p)
		 (if acc (insert acc))
		 (setq acc nil)
		 (setq pos (point)))
		(t (setq acc (concat acc (char-to-string ch)))))))
      (setq i (1+ i)))
    (if acc (insert acc))
    (if pos (goto-char pos))))

(provide 'proof-syntax)

;;; proof-syntax.el ends here