aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGlenn Morris2007-10-22 08:17:39 +0000
committerGlenn Morris2007-10-22 08:17:39 +0000
commit5ab33946cc342c850fc769e600c8e00cfb024c9d (patch)
tree77a3137a22b44dee3bc9d880025653f3a44306f9
parent640f9e264aaa0046d89bb495f22d6bdce29f74f9 (diff)
downloademacs-5ab33946cc342c850fc769e600c8e00cfb024c9d.tar.gz
emacs-5ab33946cc342c850fc769e600c8e00cfb024c9d.zip
Add some support for Fortran 2003 syntax:
(f90-type-indent): Now also applies to `enum'. (f90-associate-indent): New user option. (f90-keywords-re, f90-keywords-level-3-re, f90-procedures-re): Add some F2003 keywords. (f90-constants-re): New constant. (f90-font-lock-keywords-1): Add `associate' blocks, and `abstract Interface'. (f90-font-lock-keywords-2): Add `enumerator', `generic', `procedure', `class'. Arguments for `type'/`class' may have spaces. Add a new element for functions with specified types. Add `end enum' and `select type'. Add `implicit enumerator' and `procedure'. Add `class default' and `type is', `class is'. Fix `go to' regexp. (f90-font-lock-keywords-3): Add `asynchronous' attribute. (f90-font-lock-keywords-4): Add `f90-constants-re'. (f90-blocks-re): Add `enum' and `associate'. (f90-else-like-re): Add `class is', `type is', and `class default'. (f90-end-type-re): Add `enum'. (f90-end-associate-re, f90-typeis-re): New constants. (f90-end-block-re): Add `enum' and `associate'. Change from optional whitespace to end-of-word, to avoid `enumerator'. (f90-start-block-re): Add `select type', `abstract interface', and `enum'. Avoid `type is', and `type (sometype)'. (f90-mode-abbrev-table): Add `enumerator', `protected', and `volatile'. (f90-mode): Doc fix. (f90-looking-at-select-case): Doc fix. Add `select type'. (f90-looking-at-associate): New function, (f90-looking-at-type-like): Avoid `type is' and `type (sometype)'. Add `enum' and `abstract interface'. (f90-no-block-limit): Add `select type' and `abstract interface'. (f90-get-correct-indent, f90-calculate-indent) (f90-end-of-block, f90-beginning-of-block, f90-next-block) (f90-indent-region, f90-match-end): : Handle `associate' blocks.
-rw-r--r--lisp/ChangeLog33
-rw-r--r--lisp/progmodes/f90.el232
2 files changed, 228 insertions, 37 deletions
diff --git a/lisp/ChangeLog b/lisp/ChangeLog
index 6803add655a..d66eb3e63db 100644
--- a/lisp/ChangeLog
+++ b/lisp/ChangeLog
@@ -1,6 +1,39 @@
12007-10-22 Glenn Morris <rgm@gnu.org> 12007-10-22 Glenn Morris <rgm@gnu.org>
2 2
3 * progmodes/f90.el: Remove leading "*" from defcustom doc-strings. 3 * progmodes/f90.el: Remove leading "*" from defcustom doc-strings.
4 Add some support for Fortran 2003 syntax:
5 (f90-type-indent): Now also applies to `enum'.
6 (f90-associate-indent): New user option.
7 (f90-keywords-re, f90-keywords-level-3-re, f90-procedures-re):
8 Add some F2003 keywords.
9 (f90-constants-re): New constant.
10 (f90-font-lock-keywords-1): Add `associate' blocks, and `abstract
11 Interface'.
12 (f90-font-lock-keywords-2): Add `enumerator', `generic', `procedure',
13 `class'. Arguments for `type'/`class' may have spaces. Add a new
14 element for functions with specified types. Add `end enum' and
15 `select type'. Add `implicit enumerator' and `procedure'. Add
16 `class default' and `type is', `class is'. Fix `go to' regexp.
17 (f90-font-lock-keywords-3): Add `asynchronous' attribute.
18 (f90-font-lock-keywords-4): Add `f90-constants-re'.
19 (f90-blocks-re): Add `enum' and `associate'.
20 (f90-else-like-re): Add `class is', `type is', and `class default'.
21 (f90-end-type-re): Add `enum'.
22 (f90-end-associate-re, f90-typeis-re): New constants.
23 (f90-end-block-re): Add `enum' and `associate'. Change from
24 optional whitespace to end-of-word, to avoid `enumerator'.
25 (f90-start-block-re): Add `select type', `abstract interface', and
26 `enum'. Avoid `type is', and `type (sometype)'.
27 (f90-mode-abbrev-table): Add `enumerator', `protected', and `volatile'.
28 (f90-mode): Doc fix.
29 (f90-looking-at-select-case): Doc fix. Add `select type'.
30 (f90-looking-at-associate): New function,
31 (f90-looking-at-type-like): Avoid `type is' and `type (sometype)'.
32 Add `enum' and `abstract interface'.
33 (f90-no-block-limit): Add `select type' and `abstract interface'.
34 (f90-get-correct-indent, f90-calculate-indent)
35 (f90-end-of-block, f90-beginning-of-block, f90-next-block)
36 (f90-indent-region, f90-match-end): : Handle `associate' blocks.
4 37
52007-10-22 Martin Rudalics <rudalics@gmx.at> 382007-10-22 Martin Rudalics <rudalics@gmx.at>
6 39
diff --git a/lisp/progmodes/f90.el b/lisp/progmodes/f90.el
index ec64d936317..2bf33d2cb2e 100644
--- a/lisp/progmodes/f90.el
+++ b/lisp/progmodes/f90.el
@@ -28,6 +28,8 @@
28 28
29;; Major mode for editing F90 programs in FREE FORMAT. 29;; Major mode for editing F90 programs in FREE FORMAT.
30;; The minor language revision F95 is also supported (with font-locking). 30;; The minor language revision F95 is also supported (with font-locking).
31;; Some aspects of F2003 are supported. At present, there are some
32;; problems with derived types.
31 33
32;; Knows about continuation lines, named structured statements, and other 34;; Knows about continuation lines, named structured statements, and other
33;; features in F90 including HPF (High Performance Fortran) structures. 35;; features in F90 including HPF (High Performance Fortran) structures.
@@ -154,8 +156,12 @@
154;;; Code: 156;;; Code:
155 157
156;; TODO 158;; TODO
159;; Have "f90-mode" just recognize F90 syntax, then derived modes
160;; "f95-mode", "f2003-mode" for the language revisions.
157;; Support for align. 161;; Support for align.
158;; OpenMP, preprocessor highlighting. 162;; OpenMP, preprocessor highlighting.
163;; F2003 syntax:
164;; problems with derived types.
159 165
160(defvar comment-auto-fill-only-comments) 166(defvar comment-auto-fill-only-comments)
161(defvar font-lock-keywords) 167(defvar font-lock-keywords)
@@ -184,7 +190,7 @@
184 :group 'f90-indent) 190 :group 'f90-indent)
185 191
186(defcustom f90-type-indent 3 192(defcustom f90-type-indent 3
187 "Extra indentation applied to TYPE, INTERFACE and BLOCK DATA blocks." 193 "Extra indentation applied to TYPE, ENUM, INTERFACE and BLOCK DATA blocks."
188 :type 'integer 194 :type 'integer
189 :group 'f90-indent) 195 :group 'f90-indent)
190 196
@@ -193,6 +199,12 @@
193 :type 'integer 199 :type 'integer
194 :group 'f90-indent) 200 :group 'f90-indent)
195 201
202(defcustom f90-associate-indent 2
203 "Extra indentation applied to ASSOCIATE blocks."
204 :type 'integer
205 :group 'f90-indent
206 :version "23.1")
207
196(defcustom f90-continuation-indent 5 208(defcustom f90-continuation-indent 5
197 "Extra indentation applied to continuation lines." 209 "Extra indentation applied to continuation lines."
198 :type 'integer 210 :type 'integer
@@ -276,7 +288,13 @@ The options are 'downcase-word, 'upcase-word, 'capitalize-word and nil."
276 "rewind" "save" "select" "sequence" "stop" "subroutine" 288 "rewind" "save" "select" "sequence" "stop" "subroutine"
277 "target" "then" "type" "use" "where" "while" "write" 289 "target" "then" "type" "use" "where" "while" "write"
278 ;; F95 keywords. 290 ;; F95 keywords.
279 "elemental" "pure") 'words) 291 "elemental" "pure"
292 ;; F2003
293 "abstract" "associate" "asynchronous" "bind" "class"
294 "deferred" "enum" "enumerator" "extends" "extends_type_of"
295 "final" "generic" "import" "non_overridable" "nopass" "pass"
296 "protected" "same_type_as" "value" "volatile"
297 ) 'words)
280 "Regexp used by the function `f90-change-keywords'.") 298 "Regexp used by the function `f90-change-keywords'.")
281 299
282(defconst f90-keywords-level-3-re 300(defconst f90-keywords-level-3-re
@@ -284,11 +302,16 @@ The options are 'downcase-word, 'upcase-word, 'capitalize-word and nil."
284 '("allocatable" "allocate" "assign" "assignment" "backspace" 302 '("allocatable" "allocate" "assign" "assignment" "backspace"
285 "close" "deallocate" "dimension" "endfile" "entry" "equivalence" 303 "close" "deallocate" "dimension" "endfile" "entry" "equivalence"
286 "external" "inquire" "intent" "intrinsic" "nullify" "only" "open" 304 "external" "inquire" "intent" "intrinsic" "nullify" "only" "open"
305 ;; FIXME operator and assignment should be F2003 procedures?
287 "operator" "optional" "parameter" "pause" "pointer" "print" "private" 306 "operator" "optional" "parameter" "pause" "pointer" "print" "private"
288 "public" "read" "recursive" "result" "rewind" "save" "select" 307 "public" "read" "recursive" "result" "rewind" "save" "select"
289 "sequence" "target" "write" 308 "sequence" "target" "write"
290 ;; F95 keywords. 309 ;; F95 keywords.
291 "elemental" "pure") 'words) 310 "elemental" "pure"
311 ;; F2003. asynchronous separate.
312 "abstract" "deferred" "import" "final" "non_overridable"
313 "nopass" "pass" "protected" "value" "volatile"
314 ) 'words)
292 "Keyword-regexp for font-lock level >= 3.") 315 "Keyword-regexp for font-lock level >= 3.")
293 316
294(defconst f90-procedures-re 317(defconst f90-procedures-re
@@ -314,7 +337,19 @@ The options are 'downcase-word, 'upcase-word, 'capitalize-word and nil."
314 "sum" "system_clock" "tan" "tanh" "tiny" "transfer" 337 "sum" "system_clock" "tan" "tanh" "tiny" "transfer"
315 "transpose" "trim" "ubound" "unpack" "verify" 338 "transpose" "trim" "ubound" "unpack" "verify"
316 ;; F95 intrinsic functions. 339 ;; F95 intrinsic functions.
317 "null" "cpu_time") t) 340 "null" "cpu_time"
341 ;; F2003.
342 "move_alloc" "command_argument_count" "get_command"
343 "get_command_argument" "get_environment_variable"
344 "selected_char_kind" "wait" "flush" "new_line"
345 "extends" "extends_type_of" "same_type_as" "bind"
346 ;; F2003 ieee_arithmetic intrinsic module.
347 "ieee_support_underflow_control" "ieee_get_underflow_mode"
348 "ieee_set_underflow_mode"
349 ;; F2003 iso_c_binding intrinsic module.
350 "c_loc" "c_funloc" "c_associated" "c_f_pointer"
351 "c_f_procpointer"
352 ) t)
318 ;; A left parenthesis to avoid highlighting non-procedures. 353 ;; A left parenthesis to avoid highlighting non-procedures.
319 "[ \t]*(") 354 "[ \t]*(")
320 "Regexp whose first part matches F90 intrinsic procedures.") 355 "Regexp whose first part matches F90 intrinsic procedures.")
@@ -349,20 +384,48 @@ The options are 'downcase-word, 'upcase-word, 'capitalize-word and nil."
349 "block" "cyclic" "extrinsic" "new" "onto" "pure" "with") 'words) 384 "block" "cyclic" "extrinsic" "new" "onto" "pure" "with") 'words)
350 "Regexp for all HPF keywords, procedures and directives.") 385 "Regexp for all HPF keywords, procedures and directives.")
351 386
352;; Highlighting patterns. 387(defconst f90-constants-re
388 (regexp-opt '( ;; F2003 iso_fortran_env constants.
389 "iso_fortran_env"
390 "input_unit" "output_unit" "error_unit"
391 "iostat_end" "iostat_eor"
392 "numeric_storage_size" "character_storage_size"
393 "file_storage_size"
394 ;; F2003 iso_c_binding constants.
395 "iso_c_binding"
396 "c_int" "c_short" "c_long" "c_long_long" "c_signed_char"
397 "c_size_t"
398 "c_int8_t" "c_int16_t" "c_int32_t" "c_int64_t"
399 "c_int_least8_t" "c_int_least16_t" "c_int_least32_t"
400 "c_int_least64_t"
401 "c_int_fast8_t" "c_int_fast16_t" "c_int_fast32_t"
402 "c_int_fast64_t"
403 "c_intmax_t" "c_intptr_t"
404 "c_float" "c_double" "c_long_double"
405 "c_float_complex" "c_double_complex" "c_long_double_complex"
406 "c_bool" "c_char"
407 "c_null_char" "c_alert" "c_backspace" "c_form_feed"
408 "c_new_line" "c_carriage_return" "c_horizontal_tab"
409 "c_vertical_tab"
410 "c_ptr" "c_funptr" "c_null_ptr" "c_null_funptr"
411 ) 'words)
412 "Regexp for Fortran intrinsic constants.")
353 413
354(defvar f90-font-lock-keywords-1 414(defvar f90-font-lock-keywords-1
355 (list 415 (list
356 ;; Special highlighting of "module procedure". 416 ;; Special highlighting of "module procedure".
357 '("\\<\\(module[ \t]*procedure\\)\\>" (1 font-lock-keyword-face)) 417 '("\\<\\(module[ \t]*procedure\\)\\>" (1 font-lock-keyword-face))
358 ;; Highlight definition of derived type. 418 ;; Highlight definition of derived type.
419 ;; FIXME F2003 use a function, same as looking-at-type-like?
359 '("\\<\\(\\(?:end[ \t]*\\)?type\\)\\>\\([^()\n]*::\\)?[ \t]*\\(\\sw+\\)" 420 '("\\<\\(\\(?:end[ \t]*\\)?type\\)\\>\\([^()\n]*::\\)?[ \t]*\\(\\sw+\\)"
360 (1 font-lock-keyword-face) (3 font-lock-function-name-face)) 421 (1 font-lock-keyword-face) (3 font-lock-function-name-face))
361 ;; Other functions and declarations. 422 ;; Other functions and declarations.
362 '("\\<\\(\\(?:end[ \t]*\\)?\\(program\\|module\\|function\\|\ 423 '("\\<\\(\\(?:end[ \t]*\\)?\\(program\\|module\\|function\\|associate\\|\
363subroutine\\)\\|use\\|call\\)\\>[ \t]*\\(\\sw+\\)?" 424subroutine\\)\\|use\\|call\\)\\>[ \t]*\\(\\sw+\\)?"
364 (1 font-lock-keyword-face) (3 font-lock-function-name-face nil t)) 425 (1 font-lock-keyword-face) (3 font-lock-function-name-face nil t))
365 "\\<\\(\\(end[ \t]*\\)?\\(interface\\|block[ \t]*data\\)\\|contains\\)\\>") 426 ;; "abstract interface" is F2003.
427 "\\<\\(\\(end[ \t]*\\)?\\(\\(?:abstract[ \t]+\\)?interface\\|\
428block[ \t]*data\\)\\|contains\\)\\>")
366 "This does fairly subdued highlighting of comments and function calls.") 429 "This does fairly subdued highlighting of comments and function calls.")
367 430
368(defvar f90-font-lock-keywords-2 431(defvar f90-font-lock-keywords-2
@@ -370,20 +433,38 @@ subroutine\\)\\|use\\|call\\)\\>[ \t]*\\(\\sw+\\)?"
370 f90-font-lock-keywords-1 433 f90-font-lock-keywords-1
371 (list 434 (list
372 ;; Variable declarations (avoid the real function call). 435 ;; Variable declarations (avoid the real function call).
436 ;; FIXME type( rational_t( this_k)), intent( in) :: a, b
437 ;; maybe type should just work like integer.
438 ;; Or use forward-sexp.
373 '("^[ \t0-9]*\\(real\\|integer\\|c\\(haracter\\|omplex\\)\\|\ 439 '("^[ \t0-9]*\\(real\\|integer\\|c\\(haracter\\|omplex\\)\\|\
374logical\\|double[ \t]*precision\\|type[ \t]*(\\sw+)\\)\ 440enumerator\\|generic\\|procedure\\|\
441logical\\|double[ \t]*precision\\|\
442\\(?:type\\|class\\)[ \t]*([ \t]*\\sw+[ \t]*)\\)\
375\\(.*::\\|[ \t]*(.*)\\)?\\([^&!\n]*\\)" 443\\(.*::\\|[ \t]*(.*)\\)?\\([^&!\n]*\\)"
376 (1 font-lock-type-face t) (4 font-lock-variable-name-face t)) 444 (1 font-lock-type-face t) (4 font-lock-variable-name-face t))
377 ;; do, if, select, where, and forall constructs. 445 ;; "real function foo (args)". Must override previous. Note hack
378 '("\\<\\(end[ \t]*\\(do\\|if\\|select\\|forall\\|where\\)\\)\\>\ 446 ;; to get "args" unhighlighted again. Might not always be right,
447 ;; but probably better than leaving them as variables.
448 ;; FIXME in F2003, can specify kinds.
449 ;; integer( kind=1 ) function foo()
450 '("\\<\\(\\(real\\|integer\\|c\\(haracter\\|omplex\\)\\|\
451logical\\|double[ \t]*precision\\|\
452\\(?:type\\|class\\)[ \t]*([ \t]*\\sw+[ \t]*)\\)[ \t]*\\)\
453\\(function\\)\\>[ \t]*\\(\\sw+\\)[ \t]*\\(([^&!\n]*)\\)"
454 (1 font-lock-type-face t) (4 font-lock-keyword-face t)
455 (5 font-lock-function-name-face t) (6 'default t))
456 ;; end do, if, enum (F2003), select, where, and forall constructs.
457 '("\\<\\(end[ \t]*\\(do\\|if\\|enum\\|select\\|forall\\|where\\)\\)\\>\
379\\([ \t]+\\(\\sw+\\)\\)?" 458\\([ \t]+\\(\\sw+\\)\\)?"
380 (1 font-lock-keyword-face) (3 font-lock-constant-face nil t)) 459 (1 font-lock-keyword-face) (3 font-lock-constant-face nil t))
381 '("^[ \t0-9]*\\(\\(\\sw+\\)[ \t]*:[ \t]*\\)?\\(\\(if\\|\ 460 '("^[ \t0-9]*\\(\\(\\sw+\\)[ \t]*:[ \t]*\\)?\\(\\(if\\|enum\\|\
382do\\([ \t]*while\\)?\\|select[ \t]*case\\|where\\|forall\\)\\)\\>" 461do\\([ \t]*while\\)?\\|select[ \t]*\\(?:case\\|type\\)\\|where\\|\
462forall\\)\\)\\>"
383 (2 font-lock-constant-face nil t) (3 font-lock-keyword-face)) 463 (2 font-lock-constant-face nil t) (3 font-lock-keyword-face))
384 ;; Implicit declaration. 464 ;; Implicit declaration.
385 '("\\<\\(implicit\\)[ \t]*\\(real\\|integer\\|c\\(haracter\\|omplex\\)\ 465 '("\\<\\(implicit\\)[ \t]*\\(real\\|integer\\|c\\(haracter\\|omplex\\)\
386\\|logical\\|double[ \t]*precision\\|type[ \t]*(\\sw+)\\|none\\)[ \t]*" 466\\|enumerator\\|procedure\\|\
467logical\\|double[ \t]*precision\\|type[ \t]*(\\sw+)\\|none\\)[ \t]*"
387 (1 font-lock-keyword-face) (2 font-lock-type-face)) 468 (1 font-lock-keyword-face) (2 font-lock-type-face))
388 '("\\<\\(namelist\\|common\\)[ \t]*\/\\(\\sw+\\)?\/" 469 '("\\<\\(namelist\\|common\\)[ \t]*\/\\(\\sw+\\)?\/"
389 (1 font-lock-keyword-face) (2 font-lock-constant-face nil t)) 470 (1 font-lock-keyword-face) (2 font-lock-constant-face nil t))
@@ -393,7 +474,11 @@ do\\([ \t]*while\\)?\\|select[ \t]*case\\|where\\|forall\\)\\)\\>"
393 '("\\<\\(exit\\|cycle\\)[ \t]*\\(\\sw+\\)?\\>" 474 '("\\<\\(exit\\|cycle\\)[ \t]*\\(\\sw+\\)?\\>"
394 (1 font-lock-keyword-face) (2 font-lock-constant-face nil t)) 475 (1 font-lock-keyword-face) (2 font-lock-constant-face nil t))
395 '("\\<\\(case\\)[ \t]*\\(default\\|(\\)" . 1) 476 '("\\<\\(case\\)[ \t]*\\(default\\|(\\)" . 1)
396 '("\\<\\(do\\|go *to\\)\\>[ \t]*\\([0-9]+\\)" 477 ;; F2003 "class default".
478 '("\\<\\(class\\)[ \t]*default" . 1)
479 ;; F2003 "type is" in a "select type" block.
480 '("\\<\\(\\(type\\|class\\)[ \t]*is\\)[ \t]*(" (1 font-lock-keyword-face t))
481 '("\\<\\(do\\|go[ \t]*to\\)\\>[ \t]*\\([0-9]+\\)"
397 (1 font-lock-keyword-face) (2 font-lock-constant-face)) 482 (1 font-lock-keyword-face) (2 font-lock-constant-face))
398 ;; Line numbers (lines whose first character after number is letter). 483 ;; Line numbers (lines whose first character after number is letter).
399 '("^[ \t]*\\([0-9]+\\)[ \t]*[a-z]+" (1 font-lock-constant-face t)))) 484 '("^[ \t]*\\([0-9]+\\)[ \t]*[a-z]+" (1 font-lock-constant-face t))))
@@ -406,13 +491,16 @@ do\\([ \t]*while\\)?\\|select[ \t]*case\\|where\\|forall\\)\\)\\>"
406 f90-operators-re 491 f90-operators-re
407 (list f90-procedures-re '(1 font-lock-keyword-face keep)) 492 (list f90-procedures-re '(1 font-lock-keyword-face keep))
408 "\\<real\\>" ; avoid overwriting real defs 493 "\\<real\\>" ; avoid overwriting real defs
494 ;; As an attribute, but not as an optional argument.
495 '("\\<\\(asynchronous\\)[ \t]*[^=]" . 1)
409 )) 496 ))
410 "Highlights all F90 keywords and intrinsic procedures.") 497 "Highlights all F90 keywords and intrinsic procedures.")
411 498
412(defvar f90-font-lock-keywords-4 499(defvar f90-font-lock-keywords-4
413 (append f90-font-lock-keywords-3 500 (append f90-font-lock-keywords-3
414 (list f90-hpf-keywords-re)) 501 (list (cons f90-constants-re 'font-lock-constant-face)
415 "Highlights all F90 and HPF keywords.") 502 f90-hpf-keywords-re))
503 "Highlights all F90 and HPF keywords and constants.")
416 504
417(defvar f90-font-lock-keywords 505(defvar f90-font-lock-keywords
418 f90-font-lock-keywords-2 506 f90-font-lock-keywords-2
@@ -559,7 +647,9 @@ Can be overridden by the value of `font-lock-maximum-decoration'.")
559(defconst f90-blocks-re 647(defconst f90-blocks-re
560 (concat "\\(block[ \t]*data\\|" 648 (concat "\\(block[ \t]*data\\|"
561 (regexp-opt '("do" "if" "interface" "function" "module" "program" 649 (regexp-opt '("do" "if" "interface" "function" "module" "program"
562 "select" "subroutine" "type" "where" "forall")) 650 "select" "subroutine" "type" "where" "forall"
651 ;; F2003.
652 "enum" "associate"))
563 "\\)\\>") 653 "\\)\\>")
564 "Regexp potentially indicating a \"block\" of F90 code.") 654 "Regexp potentially indicating a \"block\" of F90 code.")
565 655
@@ -567,9 +657,11 @@ Can be overridden by the value of `font-lock-maximum-decoration'.")
567 (regexp-opt '("program" "module" "subroutine" "function") 'paren) 657 (regexp-opt '("program" "module" "subroutine" "function") 'paren)
568 "Regexp used to locate the start/end of a \"subprogram\".") 658 "Regexp used to locate the start/end of a \"subprogram\".")
569 659
660;; "class is" is F2003.
570(defconst f90-else-like-re 661(defconst f90-else-like-re
571 "\\(else\\([ \t]*if\\|where\\)?\\|case[ \t]*\\(default\\|(\\)\\)" 662 "\\(else\\([ \t]*if\\|where\\)?\\|case[ \t]*\\(default\\|(\\)\\|\
572 "Regexp matching an ELSE IF, ELSEWHERE, CASE statement.") 663\\(class\\|type\\)[ \t]*is[ \t]*(\\|class[ \t]*default\\)"
664 "Regexp matching an ELSE IF, ELSEWHERE, CASE, CLASS/TYPE IS statement.")
573 665
574(defconst f90-end-if-re 666(defconst f90-end-if-re
575 (concat "end[ \t]*" 667 (concat "end[ \t]*"
@@ -578,13 +670,27 @@ Can be overridden by the value of `font-lock-maximum-decoration'.")
578 "Regexp matching the end of an IF, SELECT, WHERE, FORALL block.") 670 "Regexp matching the end of an IF, SELECT, WHERE, FORALL block.")
579 671
580(defconst f90-end-type-re 672(defconst f90-end-type-re
581 "end[ \t]*\\(type\\|interface\\|block[ \t]*data\\)\\>" 673 "end[ \t]*\\(type\\|enum\\|interface\\|block[ \t]*data\\)\\>"
582 "Regexp matching the end of a TYPE, INTERFACE, BLOCK DATA section.") 674 "Regexp matching the end of a TYPE, ENUM, INTERFACE, BLOCK DATA section.")
675
676(defconst f90-end-associate-re
677 "end[ \t]*associate\\>"
678 "Regexp matching the end of an ASSOCIATE block.")
583 679
680;; This is for a TYPE block, not a variable of derived TYPE.
681;; Hence no need to add CLASS for F2003.
584(defconst f90-type-def-re 682(defconst f90-type-def-re
683 ;; type word
684 ;; type :: word
685 ;; type, stuff :: word
686 ;; NOT "type ("
585 "\\<\\(type\\)\\>\\(?:[^()\n]*::\\)?[ \t]*\\(\\sw+\\)" 687 "\\<\\(type\\)\\>\\(?:[^()\n]*::\\)?[ \t]*\\(\\sw+\\)"
586 "Regexp matching the definition of a derived type.") 688 "Regexp matching the definition of a derived type.")
587 689
690(defconst f90-typeis-re
691 "\\<\\(class\\|type\\)[ \t]*is[ \t]*("
692 "Regexp matching a CLASS/TYPE IS statement.")
693
588(defconst f90-no-break-re 694(defconst f90-no-break-re
589 (regexp-opt '("**" "//" "=>" ">=" "<=" "==" "/=") 'paren) 695 (regexp-opt '("**" "//" "=>" ">=" "<=" "==" "/=") 'paren)
590 "Regexp specifying where not to break lines when filling. 696 "Regexp specifying where not to break lines when filling.
@@ -603,8 +709,8 @@ characters long.")
603 (concat "^[ \t0-9]*\\<end[ \t]*" 709 (concat "^[ \t0-9]*\\<end[ \t]*"
604 (regexp-opt '("do" "if" "forall" "function" "interface" 710 (regexp-opt '("do" "if" "forall" "function" "interface"
605 "module" "program" "select" "subroutine" 711 "module" "program" "select" "subroutine"
606 "type" "where" ) t) 712 "type" "where" "enum" "associate") t)
607 "[ \t]*\\sw*") 713 "\\>")
608 "Regexp matching the end of an F90 \"block\", from the line start. 714 "Regexp matching the end of an F90 \"block\", from the line start.
609Used in the F90 entry in `hs-special-modes-alist'.") 715Used in the F90 entry in `hs-special-modes-alist'.")
610 716
@@ -615,14 +721,22 @@ Used in the F90 entry in `hs-special-modes-alist'.")
615 "^[ \t0-9]*" ; statement number 721 "^[ \t0-9]*" ; statement number
616 "\\(\\(" 722 "\\(\\("
617 "\\(\\sw+[ \t]*:[ \t]*\\)?" ; structure label 723 "\\(\\sw+[ \t]*:[ \t]*\\)?" ; structure label
618 "\\(do\\|select[ \t]*case\\|" 724 "\\(do\\|select[ \t]*\\(case\\|type\\)\\|"
619 ;; See comments in fortran-start-block-re for the problems of IF. 725 ;; See comments in fortran-start-block-re for the problems of IF.
620 "if[ \t]*(\\(.*\\|" 726 "if[ \t]*(\\(.*\\|"
621 ".*\n\\([^if]*\\([^i].\\|.[^f]\\|.\\>\\)\\)\\)\\<then\\|" 727 ".*\n\\([^if]*\\([^i].\\|.[^f]\\|.\\>\\)\\)\\)\\<then\\|"
622 ;; Distinguish WHERE block from isolated WHERE. 728 ;; Distinguish WHERE block from isolated WHERE.
623 "\\(where\\|forall\\)[ \t]*(.*)[ \t]*\\(!\\|$\\)\\)\\)" 729 "\\(where\\|forall\\)[ \t]*(.*)[ \t]*\\(!\\|$\\)\\)\\)"
624 "\\|" 730 "\\|"
625 "program\\|interface\\|module\\|type\\|function\\|subroutine" 731 ;; Avoid F2003 "type is" in "select type",
732 ;; and also variables of derived type "type (foo)".
733 ;; "type, foo" must be a block (?).
734 "type[ \t,]\\([^(is]\\|[^(i].\\|[^(][^s]\\|is\\sw\\)"
735 "\\|"
736 ;; "abstract interface" is F2003.
737 "program\\|\\(?:abstract[ \t]+\\)?interface\\|module\\|"
738 ;; "enum", but not "enumerator".
739 "function\\|subroutine\\|enum[^e]\\|associate"
626 "\\)" 740 "\\)"
627 "[ \t]*") 741 "[ \t]*")
628 "Regexp matching the start of an F90 \"block\", from the line start. 742 "Regexp matching the start of an F90 \"block\", from the line start.
@@ -637,6 +751,7 @@ Used in the F90 entry in `hs-special-modes-alist'.")
637 751
638 752
639;; Imenu support. 753;; Imenu support.
754;; FIXME F2003
640(defvar f90-imenu-generic-expression 755(defvar f90-imenu-generic-expression
641 (let ((good-char "[^!\"\&\n \t]") (not-e "[^e!\n\"\& \t]") 756 (let ((good-char "[^!\"\&\n \t]") (not-e "[^e!\n\"\& \t]")
642 (not-n "[^n!\n\"\& \t]") (not-d "[^d!\n\"\& \t]")) 757 (not-n "[^n!\n\"\& \t]") (not-d "[^d!\n\"\& \t]"))
@@ -693,6 +808,8 @@ Used in the F90 entry in `hs-special-modes-alist'.")
693 '(("`al" "allocate" ) 808 '(("`al" "allocate" )
694 ("`ab" "allocatable" ) 809 ("`ab" "allocatable" )
695 ("`as" "assignment" ) 810 ("`as" "assignment" )
811; ("`at" "abstract" )
812; ("`ay" "asynchronous" )
696 ("`ba" "backspace" ) 813 ("`ba" "backspace" )
697 ("`bd" "block data" ) 814 ("`bd" "block data" )
698 ("`c" "character" ) 815 ("`c" "character" )
@@ -709,6 +826,8 @@ Used in the F90 entry in `hs-special-modes-alist'.")
709 ("`el" "else" ) 826 ("`el" "else" )
710 ("`eli" "else if" ) 827 ("`eli" "else if" )
711 ("`elw" "elsewhere" ) 828 ("`elw" "elsewhere" )
829; ("`em" "elemental" )
830 ("`en" "enumerator" )
712 ("`eq" "equivalence" ) 831 ("`eq" "equivalence" )
713 ("`ex" "external" ) 832 ("`ex" "external" )
714 ("`ey" "entry" ) 833 ("`ey" "entry" )
@@ -731,6 +850,7 @@ Used in the F90 entry in `hs-special-modes-alist'.")
731 ("`pr" "print" ) 850 ("`pr" "print" )
732 ("`pi" "private" ) 851 ("`pi" "private" )
733 ("`pm" "program" ) 852 ("`pm" "program" )
853 ("`pr" "protected" )
734 ("`pu" "public" ) 854 ("`pu" "public" )
735 ("`r" "real" ) 855 ("`r" "real" )
736 ("`rc" "recursive" ) 856 ("`rc" "recursive" )
@@ -742,6 +862,7 @@ Used in the F90 entry in `hs-special-modes-alist'.")
742 ("`ta" "target" ) 862 ("`ta" "target" )
743 ("`tr" ".true." ) 863 ("`tr" ".true." )
744 ("`t" "type" ) 864 ("`t" "type" )
865 ("`vo" "volatile" )
745 ("`wh" "where" ) 866 ("`wh" "where" )
746 ("`wr" "write" )))) 867 ("`wr" "write" ))))
747 868
@@ -767,9 +888,9 @@ Variables controlling indentation style and extra features:
767`f90-do-indent' 888`f90-do-indent'
768 Extra indentation within do blocks (default 3). 889 Extra indentation within do blocks (default 3).
769`f90-if-indent' 890`f90-if-indent'
770 Extra indentation within if/select case/where/forall blocks (default 3). 891 Extra indentation within if/select/where/forall blocks (default 3).
771`f90-type-indent' 892`f90-type-indent'
772 Extra indentation within type/interface/block-data blocks (default 3). 893 Extra indentation within type/enum/interface/block-data blocks (default 3).
773`f90-program-indent' 894`f90-program-indent'
774 Extra indentation within program/module/subroutine/function blocks 895 Extra indentation within program/module/subroutine/function blocks
775 (default 2). 896 (default 2).
@@ -921,10 +1042,10 @@ NAME is nil if the statement has no label."
921 (list (match-string 3) (match-string 2)))) 1042 (list (match-string 3) (match-string 2))))
922 1043
923(defsubst f90-looking-at-select-case () 1044(defsubst f90-looking-at-select-case ()
924 "Return (\"select\" NAME) if a select-case statement starts after point. 1045 "Return (\"select\" NAME) if a select statement starts after point.
925NAME is nil if the statement has no label." 1046NAME is nil if the statement has no label."
926 (if (looking-at "\\(\\(\\sw+\\)[ \t]*:\\)?[ \t]*\ 1047 (if (looking-at "\\(\\(\\sw+\\)[ \t]*:\\)?[ \t]*\
927\\(select\\)[ \t]*case[ \t]*(") 1048\\(select\\)[ \t]*\\(case\\|type\\)[ \t]*(")
928 (list (match-string 3) (match-string 2)))) 1049 (list (match-string 3) (match-string 2))))
929 1050
930(defsubst f90-looking-at-if-then () 1051(defsubst f90-looking-at-if-then ()
@@ -944,6 +1065,12 @@ NAME is nil if the statement has no label."
944 (looking-at "then\\>"))) 1065 (looking-at "then\\>")))
945 (list struct label)))))) 1066 (list struct label))))))
946 1067
1068;; FIXME label?
1069(defsubst f90-looking-at-associate ()
1070 "Return (\"associate\") if an associate block starts after point."
1071 (if (looking-at "\\<\\(associate\\)[ \t]*(")
1072 (list (match-string 1))))
1073
947(defsubst f90-looking-at-where-or-forall () 1074(defsubst f90-looking-at-where-or-forall ()
948 "Return (KIND NAME) if a where or forall block starts after point. 1075 "Return (KIND NAME) if a where or forall block starts after point.
949NAME is nil if the statement has no label." 1076NAME is nil if the statement has no label."
@@ -958,12 +1085,23 @@ NAME is nil if the statement has no label."
958 (if (looking-at "\\(!\\|$\\)") (list struct label)))))) 1085 (if (looking-at "\\(!\\|$\\)") (list struct label))))))
959 1086
960(defsubst f90-looking-at-type-like () 1087(defsubst f90-looking-at-type-like ()
961 "Return (KIND NAME) if a type/interface/block-data block starts after point. 1088 "Return (KIND NAME) if a type/enum/interface/block-data starts after point.
962NAME is non-nil only for type." 1089NAME is non-nil only for type."
963 (cond 1090 (cond
964 ((looking-at f90-type-def-re) 1091 ((save-excursion
965 (list (match-string 1) (match-string 2))) 1092 (and (looking-at "\\<type[ \t]*")
966 ((looking-at "\\(interface\\|block[ \t]*data\\)\\>") 1093 (goto-char (match-end 0))
1094 (not (looking-at "\\(is\\>\\|(\\)"))
1095 (or (looking-at "\\(\\sw+\\)")
1096 (re-search-forward "[ \t]*::[ \t]*\\(\\sw+\\)"
1097 (line-end-position) t))))
1098 (list "type" (match-string 1)))
1099;;; ((and (not (looking-at f90-typeis-re))
1100;;; (looking-at f90-type-def-re))
1101;;; (list (match-string 1) (match-string 2)))
1102 ((looking-at "\\(enum\\|interface\\|block[ \t]*data\\)\\>")
1103 (list (match-string 1) nil))
1104 ((looking-at "abstract[ \t]*\\(interface\\)\\>")
967 (list (match-string 1) nil)))) 1105 (list (match-string 1) nil))))
968 1106
969(defsubst f90-looking-at-program-block-start () 1107(defsubst f90-looking-at-program-block-start ()
@@ -1046,9 +1184,9 @@ if all else fails."
1046 (save-excursion 1184 (save-excursion
1047 (not (or (looking-at "end") 1185 (not (or (looking-at "end")
1048 (looking-at "\\(do\\|if\\|else\\(if\\|where\\)?\ 1186 (looking-at "\\(do\\|if\\|else\\(if\\|where\\)?\
1049\\|select[ \t]*case\\|case\\|where\\|forall\\)\\>") 1187\\|select[ \t]*\\(case\\|type\\)\\|case\\|where\\|forall\\)\\>")
1050 (looking-at "\\(program\\|module\\|interface\\|\ 1188 (looking-at "\\(program\\|module\\|\
1051block[ \t]*data\\)\\>") 1189\\(?:abstract[ \t]+\\)?interface\\|block[ \t]*data\\)\\>")
1052 (looking-at "\\(contains\\|\\sw+[ \t]*:\\)") 1190 (looking-at "\\(contains\\|\\sw+[ \t]*:\\)")
1053 (looking-at f90-type-def-re) 1191 (looking-at f90-type-def-re)
1054 (re-search-forward "\\(function\\|subroutine\\)" 1192 (re-search-forward "\\(function\\|subroutine\\)"
@@ -1089,7 +1227,9 @@ Does not check type and subprogram indentation."
1089 ((or (f90-looking-at-if-then) 1227 ((or (f90-looking-at-if-then)
1090 (f90-looking-at-where-or-forall) 1228 (f90-looking-at-where-or-forall)
1091 (f90-looking-at-select-case)) 1229 (f90-looking-at-select-case))
1092 (setq icol (+ icol f90-if-indent)))) 1230 (setq icol (+ icol f90-if-indent)))
1231 ((f90-looking-at-associate)
1232 (setq icol (+ icol f90-associate-indent))))
1093 (end-of-line)) 1233 (end-of-line))
1094 (while (re-search-forward 1234 (while (re-search-forward
1095 "\\(if\\|do\\|select\\|where\\|forall\\)" epnt t) 1235 "\\(if\\|do\\|select\\|where\\|forall\\)" epnt t)
@@ -1101,8 +1241,12 @@ Does not check type and subprogram indentation."
1101 (f90-looking-at-where-or-forall) 1241 (f90-looking-at-where-or-forall)
1102 (f90-looking-at-select-case)) 1242 (f90-looking-at-select-case))
1103 (setq icol (+ icol f90-if-indent))) 1243 (setq icol (+ icol f90-if-indent)))
1244 ((f90-looking-at-associate)
1245 (setq icol (+ icol f90-associate-indent)))
1104 ((looking-at f90-end-if-re) 1246 ((looking-at f90-end-if-re)
1105 (setq icol (- icol f90-if-indent))) 1247 (setq icol (- icol f90-if-indent)))
1248 ((looking-at f90-end-associate-re)
1249 (setq icol (- icol f90-associate-indent)))
1106 ((looking-at "end[ \t]*do\\>") 1250 ((looking-at "end[ \t]*do\\>")
1107 (setq icol (- icol f90-do-indent)))) 1251 (setq icol (- icol f90-do-indent))))
1108 (end-of-line)) 1252 (end-of-line))
@@ -1148,6 +1292,8 @@ Does not check type and subprogram indentation."
1148 (setq icol (+ icol f90-do-indent))) 1292 (setq icol (+ icol f90-do-indent)))
1149 ((f90-looking-at-type-like) 1293 ((f90-looking-at-type-like)
1150 (setq icol (+ icol f90-type-indent))) 1294 (setq icol (+ icol f90-type-indent)))
1295 ((f90-looking-at-associate)
1296 (setq icol (+ icol f90-associate-indent)))
1151 ((or (f90-looking-at-program-block-start) 1297 ((or (f90-looking-at-program-block-start)
1152 (looking-at "contains[ \t]*\\($\\|!\\)")) 1298 (looking-at "contains[ \t]*\\($\\|!\\)"))
1153 (setq icol (+ icol f90-program-indent))))) 1299 (setq icol (+ icol f90-program-indent)))))
@@ -1165,6 +1311,8 @@ Does not check type and subprogram indentation."
1165 (setq icol (- icol f90-do-indent))) 1311 (setq icol (- icol f90-do-indent)))
1166 ((looking-at f90-end-type-re) 1312 ((looking-at f90-end-type-re)
1167 (setq icol (- icol f90-type-indent))) 1313 (setq icol (- icol f90-type-indent)))
1314 ((looking-at f90-end-associate-re)
1315 (setq icol (- icol f90-associate-indent)))
1168 ((or (looking-at "contains[ \t]*\\(!\\|$\\)") 1316 ((or (looking-at "contains[ \t]*\\(!\\|$\\)")
1169 (f90-looking-at-program-block-end)) 1317 (f90-looking-at-program-block-end))
1170 (setq icol (- icol f90-program-indent)))))) 1318 (setq icol (- icol f90-program-indent))))))
@@ -1268,6 +1416,7 @@ Interactively, pushes mark before moving point."
1268 (f90-looking-at-do) 1416 (f90-looking-at-do)
1269 (f90-looking-at-select-case) 1417 (f90-looking-at-select-case)
1270 (f90-looking-at-type-like) 1418 (f90-looking-at-type-like)
1419 (f90-looking-at-associate)
1271 (f90-looking-at-program-block-start) 1420 (f90-looking-at-program-block-start)
1272 (f90-looking-at-if-then) 1421 (f90-looking-at-if-then)
1273 (f90-looking-at-where-or-forall))) 1422 (f90-looking-at-where-or-forall)))
@@ -1328,6 +1477,7 @@ Interactively, pushes mark before moving point."
1328 (f90-looking-at-do) 1477 (f90-looking-at-do)
1329 (f90-looking-at-select-case) 1478 (f90-looking-at-select-case)
1330 (f90-looking-at-type-like) 1479 (f90-looking-at-type-like)
1480 (f90-looking-at-associate)
1331 (f90-looking-at-program-block-start) 1481 (f90-looking-at-program-block-start)
1332 (f90-looking-at-if-then) 1482 (f90-looking-at-if-then)
1333 (f90-looking-at-where-or-forall))) 1483 (f90-looking-at-where-or-forall)))
@@ -1368,6 +1518,7 @@ A block is a subroutine, if-endif, etc."
1368 (f90-looking-at-do) 1518 (f90-looking-at-do)
1369 (f90-looking-at-select-case) 1519 (f90-looking-at-select-case)
1370 (f90-looking-at-type-like) 1520 (f90-looking-at-type-like)
1521 (f90-looking-at-associate)
1371 (f90-looking-at-program-block-start) 1522 (f90-looking-at-program-block-start)
1372 (f90-looking-at-if-then) 1523 (f90-looking-at-if-then)
1373 (f90-looking-at-where-or-forall)) 1524 (f90-looking-at-where-or-forall))
@@ -1502,6 +1653,8 @@ If run in the middle of a line, the line is not broken."
1502 f90-if-indent) 1653 f90-if-indent)
1503 ((setq struct (f90-looking-at-type-like)) 1654 ((setq struct (f90-looking-at-type-like))
1504 f90-type-indent) 1655 f90-type-indent)
1656 ((setq struct (f90-looking-at-associate))
1657 f90-associate-indent)
1505 ((or (setq struct (f90-looking-at-program-block-start)) 1658 ((or (setq struct (f90-looking-at-program-block-start))
1506 (looking-at "contains[ \t]*\\($\\|!\\)")) 1659 (looking-at "contains[ \t]*\\($\\|!\\)"))
1507 f90-program-indent))) 1660 f90-program-indent)))
@@ -1535,6 +1688,8 @@ If run in the middle of a line, the line is not broken."
1535 f90-if-indent) 1688 f90-if-indent)
1536 ((setq struct (f90-looking-at-type-like)) 1689 ((setq struct (f90-looking-at-type-like))
1537 f90-type-indent) 1690 f90-type-indent)
1691 ((setq struct (f90-looking-at-associate))
1692 f90-associate-indent)
1538 ((setq struct (f90-looking-at-program-block-start)) 1693 ((setq struct (f90-looking-at-program-block-start))
1539 f90-program-indent))) 1694 f90-program-indent)))
1540 (setq ind-curr ind-lev) 1695 (setq ind-curr ind-lev)
@@ -1551,6 +1706,8 @@ If run in the middle of a line, the line is not broken."
1551 (cond ((looking-at f90-end-if-re) f90-if-indent) 1706 (cond ((looking-at f90-end-if-re) f90-if-indent)
1552 ((looking-at "end[ \t]*do\\>") f90-do-indent) 1707 ((looking-at "end[ \t]*do\\>") f90-do-indent)
1553 ((looking-at f90-end-type-re) f90-type-indent) 1708 ((looking-at f90-end-type-re) f90-type-indent)
1709 ((looking-at f90-end-associate-re)
1710 f90-associate-indent)
1554 ((f90-looking-at-program-block-end) 1711 ((f90-looking-at-program-block-end)
1555 f90-program-indent))) 1712 f90-program-indent)))
1556 (if ind-b (setq ind-lev (- ind-lev ind-b))) 1713 (if ind-b (setq ind-lev (- ind-lev ind-b)))
@@ -1753,6 +1910,7 @@ Leave point at the end of line."
1753 (f90-looking-at-where-or-forall) 1910 (f90-looking-at-where-or-forall)
1754 (f90-looking-at-select-case) 1911 (f90-looking-at-select-case)
1755 (f90-looking-at-type-like) 1912 (f90-looking-at-type-like)
1913 (f90-looking-at-associate)
1756 (f90-looking-at-program-block-start) 1914 (f90-looking-at-program-block-start)
1757 ;; Interpret a single END without a block 1915 ;; Interpret a single END without a block
1758 ;; start to be the END of a program block 1916 ;; start to be the END of a program block