aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGlenn Morris2007-10-25 03:51:15 +0000
committerGlenn Morris2007-10-25 03:51:15 +0000
commitb1ca774080d290dcb447075988073d1495721aaa (patch)
tree7b9b6d8addaba49e3916450f178764a9f78c378a
parent45b778a67734641dd138b5d333cd4b09a88ea55c (diff)
downloademacs-b1ca774080d290dcb447075988073d1495721aaa.tar.gz
emacs-b1ca774080d290dcb447075988073d1495721aaa.zip
(f90-keywords-re, f90-keywords-level-3-re): Add `non_intrinsic'.
(f90-constants-re): Add ieee modules. (f90-typedef-matcher, f90-typedec-matcher) (f90-imenu-type-matcher): New functions. (f90-font-lock-keywords-1): Give module procedures function-name face. Use `f90-typedef-matcher' for derived types. Fix `abstract interface'. Add `use, intrinsic'. (f90-font-lock-keywords-2): Use `f90-typedec-matcher' for derived types. Move start of `enum' blocks to separate entry. (f90-start-block-re): Fix `type', `abstract interface'. (f90-imenu-generic-expression): Use `f90-imenu-type-matcher' for derived types. (f90-mode-abbrev-table): Add `abstract interface', `asynchronous', `elemental', change `enumerator'. (f90-no-block-limit): Fix `abstract interface'.
-rw-r--r--lisp/progmodes/f90.el193
1 files changed, 155 insertions, 38 deletions
diff --git a/lisp/progmodes/f90.el b/lisp/progmodes/f90.el
index 687d285e57b..c590b1c55b2 100644
--- a/lisp/progmodes/f90.el
+++ b/lisp/progmodes/f90.el
@@ -28,8 +28,7 @@
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 31;; Some/many (?) aspects of F2003 are supported.
32;; problems with derived types.
33 32
34;; Knows about continuation lines, named structured statements, and other 33;; Knows about continuation lines, named structured statements, and other
35;; features in F90 including HPF (High Performance Fortran) structures. 34;; features in F90 including HPF (High Performance Fortran) structures.
@@ -156,12 +155,16 @@
156;;; Code: 155;;; Code:
157 156
158;; TODO 157;; TODO
159;; Have "f90-mode" just recognize F90 syntax, then derived modes 158;; 1. Any missing F2003 syntax?
159;; 2. Have "f90-mode" just recognize F90 syntax, then derived modes
160;; "f95-mode", "f2003-mode" for the language revisions. 160;; "f95-mode", "f2003-mode" for the language revisions.
161;; Support for align. 161;; 3. Support for align.
162;; OpenMP, preprocessor highlighting. 162;; Font-locking:
163;; F2003 syntax: 163;; 1. OpenMP, OpenMPI?, preprocessor highlighting.
164;; problems with derived types. 164;; 2. interface blah - Highlight "blah" in function-name face?
165;; Need to avoid "interface operator (+)" etc.
166;; 3. integer_name = 1
167;; 4. Labels for "else" statements (F2003)?
165 168
166(defvar comment-auto-fill-only-comments) 169(defvar comment-auto-fill-only-comments)
167(defvar font-lock-keywords) 170(defvar font-lock-keywords)
@@ -312,8 +315,8 @@ The options are 'downcase-word, 'upcase-word, 'capitalize-word and nil."
312 ;; F2003 315 ;; F2003
313 "abstract" "associate" "asynchronous" "bind" "class" 316 "abstract" "associate" "asynchronous" "bind" "class"
314 "deferred" "enum" "enumerator" "extends" "extends_type_of" 317 "deferred" "enum" "enumerator" "extends" "extends_type_of"
315 "final" "generic" "import" "non_overridable" "nopass" "pass" 318 "final" "generic" "import" "non_intrinsic" "non_overridable"
316 "protected" "same_type_as" "value" "volatile" 319 "nopass" "pass" "protected" "same_type_as" "value" "volatile"
317 ) 'words) 320 ) 'words)
318 "Regexp used by the function `f90-change-keywords'.") 321 "Regexp used by the function `f90-change-keywords'.")
319 322
@@ -329,7 +332,7 @@ The options are 'downcase-word, 'upcase-word, 'capitalize-word and nil."
329 ;; F95 keywords. 332 ;; F95 keywords.
330 "elemental" "pure" 333 "elemental" "pure"
331 ;; F2003. asynchronous separate. 334 ;; F2003. asynchronous separate.
332 "abstract" "deferred" "import" "final" "non_overridable" 335 "abstract" "deferred" "import" "final" "non_intrinsic" "non_overridable"
333 "nopass" "pass" "protected" "value" "volatile" 336 "nopass" "pass" "protected" "value" "volatile"
334 ) 'words) 337 ) 'words)
335 "Keyword-regexp for font-lock level >= 3.") 338 "Keyword-regexp for font-lock level >= 3.")
@@ -428,56 +431,145 @@ The options are 'downcase-word, 'upcase-word, 'capitalize-word and nil."
428 "c_new_line" "c_carriage_return" "c_horizontal_tab" 431 "c_new_line" "c_carriage_return" "c_horizontal_tab"
429 "c_vertical_tab" 432 "c_vertical_tab"
430 "c_ptr" "c_funptr" "c_null_ptr" "c_null_funptr" 433 "c_ptr" "c_funptr" "c_null_ptr" "c_null_funptr"
434 "ieee_exceptions"
435 "ieee_arithmetic"
436 "ieee_features"
431 ) 'words) 437 ) 'words)
432 "Regexp for Fortran intrinsic constants.") 438 "Regexp for Fortran intrinsic constants.")
433 439
440;; cf f90-looking-at-type-like.
441(defun f90-typedef-matcher (limit)
442 "Search for the start/end of the definition of a derived type, up to LIMIT.
443Set the match data so that subexpression 1,2 are the TYPE, and
444type-name parts, respectively."
445 (let (found l)
446 (while (and (re-search-forward "\\<\\(\\(?:end[ \t]*\\)?type\\)[ \t]*"
447 limit t)
448 (not (setq found
449 (progn
450 (setq l (match-data))
451 (unless (looking-at "\\(is\\>\\|(\\)")
452 (when (if (looking-at "\\(\\sw+\\)")
453 (goto-char (match-end 0))
454 (re-search-forward
455 "[ \t]*::[ \t]*\\(\\sw+\\)"
456 (line-end-position) t))
457 ;; 0 is wrong, but we don't use it.
458 (set-match-data
459 (append l (list (match-beginning 1)
460 (match-end 1))))
461 t)))))))
462 found))
463
434(defvar f90-font-lock-keywords-1 464(defvar f90-font-lock-keywords-1
435 (list 465 (list
436 ;; Special highlighting of "module procedure". 466 ;; Special highlighting of "module procedure".
437 '("\\<\\(module[ \t]*procedure\\)\\>" (1 font-lock-keyword-face)) 467 '("\\<\\(module[ \t]*procedure\\)\\>\\([^()\n]*::\\)?[ \t]*\\([^&!\n]*\\)"
468 (1 font-lock-keyword-face) (3 font-lock-function-name-face nil t))
438 ;; Highlight definition of derived type. 469 ;; Highlight definition of derived type.
439 ;; FIXME F2003 use a function, same as looking-at-type-like? 470;;; '("\\<\\(\\(?:end[ \t]*\\)?type\\)\\>\\([^()\n]*::\\)?[ \t]*\\(\\sw+\\)"
440 '("\\<\\(\\(?:end[ \t]*\\)?type\\)\\>\\([^()\n]*::\\)?[ \t]*\\(\\sw+\\)" 471;;; (1 font-lock-keyword-face) (3 font-lock-function-name-face))
441 (1 font-lock-keyword-face) (3 font-lock-function-name-face)) 472 '(f90-typedef-matcher
473 (1 font-lock-keyword-face) (2 font-lock-function-name-face))
442 ;; Other functions and declarations. 474 ;; Other functions and declarations.
443 '("\\<\\(\\(?:end[ \t]*\\)?\\(program\\|module\\|function\\|associate\\|\ 475 '("\\<\\(\\(?:end[ \t]*\\)?\\(program\\|module\\|function\\|associate\\|\
444subroutine\\)\\|use\\|call\\)\\>[ \t]*\\(\\sw+\\)?" 476subroutine\\)\\|use\\|call\\)\\>[ \t]*\\(\\sw+\\)?"
445 (1 font-lock-keyword-face) (3 font-lock-function-name-face nil t)) 477 (1 font-lock-keyword-face) (3 font-lock-function-name-face nil t))
446 ;; "abstract interface" is F2003. 478 ;; F2003.
447 "\\<\\(\\(end[ \t]*\\)?\\(\\(?:abstract[ \t]+\\)?interface\\|\ 479 '("\\<\\(use\\)[ \t]*,[ \t]*\\(\\(?:non_\\)?intrinsic\\)[ \t]*::[ \t]*\
448block[ \t]*data\\)\\|contains\\)\\>") 480\\(\\sw+\\)"
481 (1 font-lock-keyword-face) (2 font-lock-keyword-face)
482 (3 font-lock-function-name-face))
483 "\\<\\(\\(end[ \t]*\\)?block[ \t]*data\\|contains\\|\
484end[ \t]*interface\\)\\>"
485 ;; "abstract interface" is F2003. Must come after previous entry.
486 '("\\<\\(\\(?:abstract[ \t]*\\)?interface\\)\\>"
487 ;; [ \t]*\\(\\(\\sw+\\)[ \t]*[^(]\\)?"
488 ;; (2) messes up "interface operator ()", etc.
489 (1 font-lock-keyword-face))) ;(2 font-lock-function-name-face nil t)))
449 "This does fairly subdued highlighting of comments and function calls.") 490 "This does fairly subdued highlighting of comments and function calls.")
450 491
492;; NB not explicitly handling this, yet it seems to work.
493;; type(...) function foo()
494(defun f90-typedec-matcher (limit)
495 "Search for the declaration of variables of derived type, up to LIMIT.
496Set the match data so that subexpression 1,2 are the TYPE(...),
497and variable-name parts, respectively."
498 ;; Matcher functions must return nil only when there are no more
499 ;; matches within the search range.
500 (let (found l)
501 (while (and (re-search-forward "\\<\\(type\\|class\\)[ \t]*(" limit t)
502 (not
503 (setq found
504 (condition-case nil
505 (progn
506 ;; Set l after this to just highlight
507 ;; the "type" part.
508 (backward-char 1)
509 ;; Needed for: type( foo(...) ) :: bar
510 (forward-sexp)
511 (setq l (list (match-beginning 0) (point)))
512 (skip-chars-forward " \t")
513 (when
514 (re-search-forward
515 ;; type (foo) bar, qux
516 (if (looking-at "\\sw+")
517 "\\([^&!\n]+\\)"
518 ;; type (foo), stuff :: bar, qux
519 "::[ \t]*\\([^&!\n]+\\)")
520 (line-end-position) t)
521 (set-match-data
522 (append (list (car l) (match-end 1))
523 l (list (match-beginning 1)
524 (match-end 1))))
525 t))
526 (error nil))))))
527 found))
528
451(defvar f90-font-lock-keywords-2 529(defvar f90-font-lock-keywords-2
452 (append 530 (append
453 f90-font-lock-keywords-1 531 f90-font-lock-keywords-1
454 (list 532 (list
455 ;; Variable declarations (avoid the real function call). 533 ;; Variable declarations (avoid the real function call).
456 ;; FIXME type( rational_t( this_k)), intent( in) :: a, b 534 ;; NB by accident (?), this correctly fontifies the "integer" in:
457 ;; maybe type should just work like integer. 535 ;; integer () function foo ()
458 ;; Or use forward-sexp. 536 ;; because "() function foo ()" matches \\3.
459 '("^[ \t0-9]*\\(real\\|integer\\|c\\(haracter\\|omplex\\)\\|\ 537 ;; The "pure" part does not really belong here, but was added to
460enumerator\\|generic\\|procedure\\|\ 538 ;; exploit that hack.
461logical\\|double[ \t]*precision\\|\ 539 ;; The "function foo" bit is correctly fontified by keywords-1.
462\\(?:type\\|class\\)[ \t]*([ \t]*\\sw+[ \t]*)\\)\ 540 ;; TODO ? actually check for balanced parens in that case.
541 '("^[ \t0-9]*\\(?:pure\\|elemental\\)?[ \t]*\
542\\(real\\|integer\\|c\\(haracter\\|omplex\\)\\|\
543enumerator\\|generic\\|procedure\\|logical\\|double[ \t]*precision\\)\
463\\(.*::\\|[ \t]*(.*)\\)?\\([^&!\n]*\\)" 544\\(.*::\\|[ \t]*(.*)\\)?\\([^&!\n]*\\)"
464 (1 font-lock-type-face t) (4 font-lock-variable-name-face t)) 545 (1 font-lock-type-face t) (4 font-lock-variable-name-face t))
546 ;; Derived type/class variables.
547 ;; TODO ? If we just highlighted the "type" part, rather than
548 ;; "type(...)", this could be in the previous expression. And this
549 ;; would be consistent with integer( kind=8 ), etc.
550 '(f90-typedec-matcher
551 (1 font-lock-type-face) (2 font-lock-variable-name-face))
465 ;; "real function foo (args)". Must override previous. Note hack 552 ;; "real function foo (args)". Must override previous. Note hack
466 ;; to get "args" unhighlighted again. Might not always be right, 553 ;; to get "args" unhighlighted again. Might not always be right,
467 ;; but probably better than leaving them as variables. 554 ;; but probably better than leaving them as variables.
468 ;; FIXME in F2003, can specify kinds. 555 ;; NB not explicitly handling this case:
469 ;; integer( kind=1 ) function foo() 556 ;; integer( kind=1 ) function foo()
557 ;; thanks to the happy accident described above.
558 ;; Not anchored, so don't need to worry about "pure" etc.
470 '("\\<\\(\\(real\\|integer\\|c\\(haracter\\|omplex\\)\\|\ 559 '("\\<\\(\\(real\\|integer\\|c\\(haracter\\|omplex\\)\\|\
471logical\\|double[ \t]*precision\\|\ 560logical\\|double[ \t]*precision\\|\
472\\(?:type\\|class\\)[ \t]*([ \t]*\\sw+[ \t]*)\\)[ \t]*\\)\ 561\\(?:type\\|class\\)[ \t]*([ \t]*\\sw+[ \t]*)\\)[ \t]*\\)\
473\\(function\\)\\>[ \t]*\\(\\sw+\\)[ \t]*\\(([^&!\n]*)\\)" 562\\(function\\)\\>[ \t]*\\(\\sw+\\)[ \t]*\\(([^&!\n]*)\\)"
474 (1 font-lock-type-face t) (4 font-lock-keyword-face t) 563 (1 font-lock-type-face t) (4 font-lock-keyword-face t)
475 (5 font-lock-function-name-face t) (6 'default t)) 564 (5 font-lock-function-name-face t) (6 'default t))
476 ;; end do, if, enum (F2003), select, where, and forall constructs. 565 ;; enum (F2003; cf type in -1).
566 '("\\<\\(enum\\)\\>\\([^()\n]*::\\)?[ \t]*\\(\\sw+\\)"
567 (1 font-lock-keyword-face) (3 font-lock-function-name-face))
568 ;; end do, enum (F2003), if, select, where, and forall constructs.
477 '("\\<\\(end[ \t]*\\(do\\|if\\|enum\\|select\\|forall\\|where\\)\\)\\>\ 569 '("\\<\\(end[ \t]*\\(do\\|if\\|enum\\|select\\|forall\\|where\\)\\)\\>\
478\\([ \t]+\\(\\sw+\\)\\)?" 570\\([ \t]+\\(\\sw+\\)\\)?"
479 (1 font-lock-keyword-face) (3 font-lock-constant-face nil t)) 571 (1 font-lock-keyword-face) (3 font-lock-constant-face nil t))
480 '("^[ \t0-9]*\\(\\(\\sw+\\)[ \t]*:[ \t]*\\)?\\(\\(if\\|enum\\|\ 572 '("^[ \t0-9]*\\(\\(\\sw+\\)[ \t]*:[ \t]*\\)?\\(\\(if\\|\
481do\\([ \t]*while\\)?\\|select[ \t]*\\(?:case\\|type\\)\\|where\\|\ 573do\\([ \t]*while\\)?\\|select[ \t]*\\(?:case\\|type\\)\\|where\\|\
482forall\\)\\)\\>" 574forall\\)\\)\\>"
483 (2 font-lock-constant-face nil t) (3 font-lock-keyword-face)) 575 (2 font-lock-constant-face nil t) (3 font-lock-keyword-face))
@@ -751,10 +843,12 @@ Used in the F90 entry in `hs-special-modes-alist'.")
751 ;; Avoid F2003 "type is" in "select type", 843 ;; Avoid F2003 "type is" in "select type",
752 ;; and also variables of derived type "type (foo)". 844 ;; and also variables of derived type "type (foo)".
753 ;; "type, foo" must be a block (?). 845 ;; "type, foo" must be a block (?).
754 "type[ \t,]\\([^(is]\\|[^(i].\\|[^(][^s]\\|is\\sw\\)" 846 "type[ \t,]\\("
755 "\\|" 847 "[^i(!\n\"\& \t]\\|" ; not-i(
848 "i[^s!\n\"\& \t]\\|" ; i not-s
849 "is\\sw\\)\\|"
756 ;; "abstract interface" is F2003. 850 ;; "abstract interface" is F2003.
757 "program\\|\\(?:abstract[ \t]+\\)?interface\\|module\\|" 851 "program\\|\\(?:abstract[ \t]*\\)?interface\\|module\\|"
758 ;; "enum", but not "enumerator". 852 ;; "enum", but not "enumerator".
759 "function\\|subroutine\\|enum[^e]\\|associate" 853 "function\\|subroutine\\|enum[^e]\\|associate"
760 "\\)" 854 "\\)"
@@ -771,14 +865,37 @@ Used in the F90 entry in `hs-special-modes-alist'.")
771 865
772 866
773;; Imenu support. 867;; Imenu support.
774;; FIXME F2003 868;; FIXME trivial to extend this to enum. Worth it?
869(defun f90-imenu-type-matcher ()
870 "Search backward for the start of a derived type.
871Set subexpression 1 in the match-data to the name of the type."
872 (let (found l)
873 (while (and (re-search-backward "^[ \t0-9]*type[ \t]*" nil t)
874 (not (setq found
875 (save-excursion
876 (goto-char (match-end 0))
877 (unless (looking-at "\\(is\\>\\|(\\)")
878 (or (looking-at "\\(\\sw+\\)")
879 (re-search-forward
880 "[ \t]*::[ \t]*\\(\\sw+\\)"
881 (line-end-position) t))))))))
882 found))
883
775(defvar f90-imenu-generic-expression 884(defvar f90-imenu-generic-expression
776 (let ((good-char "[^!\"\&\n \t]") (not-e "[^e!\n\"\& \t]") 885 (let ((good-char "[^!\"\&\n \t]") (not-e "[^e!\n\"\& \t]")
777 (not-n "[^n!\n\"\& \t]") (not-d "[^d!\n\"\& \t]")) 886 (not-n "[^n!\n\"\& \t]") (not-d "[^d!\n\"\& \t]")
887 (not-ib "[^i(!\n\"\& \t]") (not-s "[^s!\n\"\& \t]"))
778 (list 888 (list
779 '(nil "^[ \t0-9]*program[ \t]+\\(\\sw+\\)" 1) 889 '(nil "^[ \t0-9]*program[ \t]+\\(\\sw+\\)" 1)
780 '("Modules" "^[ \t0-9]*module[ \t]+\\(\\sw+\\)[ \t]*\\(!\\|$\\)" 1) 890 '("Modules" "^[ \t0-9]*module[ \t]+\\(\\sw+\\)[ \t]*\\(!\\|$\\)" 1)
781 '("Types" "^[ \t0-9]*type[ \t]+\\(\\sw+\\)" 1) 891 (list "Types" 'f90-imenu-type-matcher 1)
892 ;; Does not handle: "type[, stuff] :: foo".
893;;; (format "^[ \t0-9]*type[ \t]+\\(\\(%s\\|i%s\\|is\\sw\\)\\sw*\\)"
894;;; not-ib not-s)
895;;; 1)
896 ;; Can't get the subexpression numbers to match in the two branches.
897;;; (format "^[ \t0-9]*type\\([ \t]*,.*\\(::\\)[ \t]*\\(\\sw+\\)\\|[ \t]+\\(\\(%s\\|i%s\\|is\\sw\\)\\sw*\\)\\)" not-ib not-s)
898;;; 3)
782 (list 899 (list
783 "Procedures" 900 "Procedures"
784 (concat 901 (concat
@@ -827,9 +944,9 @@ Used in the F90 entry in `hs-special-modes-alist'.")
827 (append element '(nil 0))))))) 944 (append element '(nil 0)))))))
828 '(("`al" "allocate" ) 945 '(("`al" "allocate" )
829 ("`ab" "allocatable" ) 946 ("`ab" "allocatable" )
947 ("`ai" "abstract interface")
830 ("`as" "assignment" ) 948 ("`as" "assignment" )
831; ("`at" "abstract" ) 949 ("`asy" "asynchronous" )
832; ("`ay" "asynchronous" )
833 ("`ba" "backspace" ) 950 ("`ba" "backspace" )
834 ("`bd" "block data" ) 951 ("`bd" "block data" )
835 ("`c" "character" ) 952 ("`c" "character" )
@@ -846,8 +963,8 @@ Used in the F90 entry in `hs-special-modes-alist'.")
846 ("`el" "else" ) 963 ("`el" "else" )
847 ("`eli" "else if" ) 964 ("`eli" "else if" )
848 ("`elw" "elsewhere" ) 965 ("`elw" "elsewhere" )
849; ("`em" "elemental" ) 966 ("`em" "elemental" )
850 ("`en" "enumerator" ) 967 ("`e" "enumerator" )
851 ("`eq" "equivalence" ) 968 ("`eq" "equivalence" )
852 ("`ex" "external" ) 969 ("`ex" "external" )
853 ("`ey" "entry" ) 970 ("`ey" "entry" )
@@ -1206,7 +1323,7 @@ if all else fails."
1206 (looking-at "\\(do\\|if\\|else\\(if\\|where\\)?\ 1323 (looking-at "\\(do\\|if\\|else\\(if\\|where\\)?\
1207\\|select[ \t]*\\(case\\|type\\)\\|case\\|where\\|forall\\)\\>") 1324\\|select[ \t]*\\(case\\|type\\)\\|case\\|where\\|forall\\)\\>")
1208 (looking-at "\\(program\\|module\\|\ 1325 (looking-at "\\(program\\|module\\|\
1209\\(?:abstract[ \t]+\\)?interface\\|block[ \t]*data\\)\\>") 1326\\(?:abstract[ \t]*\\)?interface\\|block[ \t]*data\\)\\>")
1210 (looking-at "\\(contains\\|\\sw+[ \t]*:\\)") 1327 (looking-at "\\(contains\\|\\sw+[ \t]*:\\)")
1211 (looking-at f90-type-def-re) 1328 (looking-at f90-type-def-re)
1212 (re-search-forward "\\(function\\|subroutine\\)" 1329 (re-search-forward "\\(function\\|subroutine\\)"