emacs-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

hide/show mode definitions for g77


From: David McKee
Subject: hide/show mode definitions for g77
Date: Mon, 25 Oct 2004 13:16:07 -0400 (EDT)

Folks,
   Please find, below, a first stab at hide/show mode definitions for the
g77 dialect of Fortran. 

The code is derived from a f90 mode posted to the Usenet in 2002 by Glenn
Morris---who has given me his permission to submit this work---and
functions pretty well for programs written using structured block pairs. No
attempt is made to handle strict fortran 77 syntax in which blocks are
delimited with CONTINUEs and GO TOs.

This code has received little testing to date---I have show it to some
colleagues working on the same code I wanted it for, but have not heard
back from anyone. Also note that I am by no means a lisp programmer.

No guarantees or warranty, etc.

The code is also availible at:

        <http://www.jlab.org/~dmckee/G0/g77_hs_mode.el>

-- 
-- David McKee
-- address@hidden
-- (757) 269-7492    (Office)


===========================

;; g77 fortran dialect hide-show mode definition.
;;
;; 19--22 October 2004  David W. McKee
;; Version 0.1  
;; Initial implementation.
;;
;; Hacked up from a f90 mode posted to the usenet:
;; From: Glenn Morris
;; Newsgroups: gnu.emacs.help </groups?hl=en&lr=&group=gnu.emacs.help>
;; Date: 2002-04-26 18:58:34 PST

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Features and what not:
;; ----------------------
;; ==> Tries to work with the g77 dialect
;;
;; ==> Assume that the code is as structured as possible.  Indeed, we
;; make no attempt to deal with unstructured code. If you don't use
;; endif, enddo, etc. this code won't help you.
;;
;; ==> Identifies "IF" statements as block starts by finding the
;; "THEN" part, so that the condition remains visible after hiding.
;; Similarly for "WHILE (..) DO"

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Known bugs in the f77 version:
;; ------------------------------
;; 22 October 2004 David McKee 
;;
;; ==> Comment hiding doesn't seem to work work. I don't understand
;; what it's supposed to do so I don't know where to go from here.
;;
;; ==> "CONTINUE" is a difficult case and is not treated at all.
;;
;; ==> Condition-at-the-end loops are often implemented as:
;;
;;    10   DO
;;         ...
;;         IF (...) GOTO 10
;;         ENDDO
;;
;; which will have the conditional hidden. Too bad.
;;
;; ==> I've cheeted in the ident-or-num regular expression, and it
;; will accept some constructions that the compiler will
;; reject. eg. "1abc" and the like...
;;
;; ==> So far it has recieved very little testing.

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defvar fortran-line-start-regexp "^\\ *[0-9]*\\ *" 
  "Allow for arbitrary white space at the start of a line.")

(defvar fortran-ident-regexp "\\<[A-Za-z][A-Za-z0-9_]*\\>" 
  "Regular expresion for fortran identifiers.")

;; Not precisly correct, but probably do the trick anyway
(defvar fortran-ident-or-num-regexp "\\<[A-Za-z0-9][A-Za-z0-9_]*\\>" 
  "")

;; Block "IF (..) THEN" and "WHIE (...) DO" statements could easily span
;; lines, so we select the block start on the ending keyword...
(defvar fortran-block-start-regexp
  (concat fortran-line-start-regexp
          "\\("
          "\\(" "\\<program\\>[ \t]+" fortran-ident-regexp "\\)" "\\|" 
          "\\(" "\\<subroutine\\>[ \t]+" fortran-ident-regexp 
                                         "[ \t]*([^)]*)" "\\)" "\\|" 
          "\\(" fortran-ident-regexp "[ \t]+\\<function\\>[ \t]+" 
                                     fortran-ident-regexp "[ \t]*([^)]*)" 
                                     "\\)" "\\|"
          ;; 'if (...) then'
          ;; Note that 'if' without 'then' does not mark a block
          "\\(" ".*\\<then\\>" "\\)" "\\|"
          ;; basic iterative 'do's
          "\\(" "\\<do\\>[ \t]*[0-9]*[ \t]+" fortran-ident-regexp 
                                       "[ \t]*=[ \t]*"
                                       fortran-ident-or-num-regexp 
                                       "\\([ \t]*,[ \t]*" 
                                           fortran-ident-or-num-regexp 
                                       "\\)+" "\\)" "\\|"
          ;; do forever syle unconditional loop,
          ;; also picks up 'while (...) do' constructs...
          ;;
          ;; Should proceed the while (..) do branch
          "\\(" "\\<do\\>[ \t]$" "\\)" "\\|"
          ;; 'do while (...)'
          ;; fails when the condition spans lines...
          ;; but this does not seem to be part of the g77 dialect in any case
          "\\(" ".*\\<while\\>[ \t]*([^)]*)" "\\([ \t]*\\<do\\>\\)?" 
                                             "\\)" "\\|"
          ;;
          ;; ELSE only starts a block if it is not followed by an IF
          ;; for ELSE IF constructs, we start on the THEN.
          ;; Look at fortran-block-end-start-regexp and the handling
          ;; in fortran-forward-block...
          "\\(" "\\<else\\>\\s *\\(!.*\\)?$" "\\)"
          "\\)"
          )
  "Regexp matching the start of a \"block\" of FORTRAN code.")

(defvar fortran-block-end-regexp
  (concat fortran-line-start-regexp 
          "\\("
          ;; structured fortran uses 'end<stuff>'
          "\\(" "\\<enddo\\>" "\\)" "\\|" 
          "\\(" "\\<endif\\>" "\\)" "\\|" 
          ;; some dialects
          "\\(" "\\<endwhile\\>" "\\)" "\\|" 
          ;; end<space>[if|do|while]type stuff
          "\\(" "\\<end\\>[ \t]+" fortran-ident-regexp "\\)" "\\|" 
          ;; catchall
          "\\(" "\\<end\\>" "\\)" "\\|"
          ;; CONTINUE causes trouble, it marks the end of old-fashioned
          ;; do i=start,stop,inc type loops, but also serves as a 
          ;; general labeling construct.
          ;;
          ;; leave it out by default
             ;; "\\(" "\\<continue\\>" "\\)" 
          ;;
          ;; Start and end bock markers...
          ;;
          "\\(" "\\<elseif\\>" "\\)" "\\|"
          "\\(" "\\<else\\>\\s +\\<if\\>" "\\)" "\\|"
          "\\(" "\\<else\\>" "\\)"
          "\\)"
          )
  "Regexp matching the end of a \"block\" of FORTRAN code.")

(defvar fortran-block-end-start-regexp
  (concat fortran-line-start-regexp
          "\\("
          "\\(" "\\<elseif\\>" "\\)" "\\|"
          "\\(" "\\<else\\>\\s +\\<if\\>" "\\)" "\\|"
          "\\(" "\\<else\\>\\s +\\<if\\>" "\\)"
          "\\)"
          )
  "Regexp matching a construct that marks the end of one \"block\" of
FORTRAN code, and the start of another. At this time this is only
ELSEIF constructs and ELSE statements.")

(defvar fortran-comment-regexp
  (concat ;;"\\("
          "\\(" "^[CcDd\\*]" "\\)" ;;"\\|" 
          ;;"\\(" "^\\s *!.*$" "\\)"
          ;;"\\)"
          )
  "Regular expression for identifiying block comments in fortran")

;; Utility functions for checking my regexps
(defun fortran-find-next-block-start ()
  "Search forward to the next line matching fortran-block-end-regexp."
  (interactive)
  (search-forward-regexp fortran-block-start-regexp))

(defun fortran-find-next-block-end ()
  "Search forward to the next line matching fortran-block-end-regexp."
  (interactive)
  (search-forward-regexp fortran-block-end-regexp))

(defun fortran-next-block-start (arg)
  "Move forward a line at a time until we reach one matching 
fortran-block-start-regexp." 
  (interactive "p")
  (while (and (zerop (forward-line 1))
              (not (looking-at fortran-block-start-regexp))) 
    (forward-line 1)))

(defun fortran-find-end-start-start ()
  "Move the point to the beginning of the next line--including the current
line--which matches fortran-block-start-regexp"
  (interactive)
  ((beginning-of-line)
   (while (null (looking-at fortran-block-start-regexg))
     (forward-line 1))
   (begining-of-line)))

(defun fortran-find-end-start-end ()
  "Move the point to the beginning of the most recent line--including
the current line--which matches fortran-block-end-regexp"
  (interactive)
  (beginning-of-line)
  (while (null (looking-at fortran-block-end-regexg))
    (forward-line -1))
  (beginning-of-line))

(defun fortran-forward-block (arg)
  "Move point to the forward until reaching exiting ARG levels of blocks"
  (interactive "p")
  (let ((count (or arg 1)))
    (while (and (> count 0) (zerop (forward-line 1)))
      (if (looking-at fortran-block-end-regexp) (setq count (1- count)))
      (and (> count 0) ()
        (if (looking-at fortran-block-end-start-regexp) 
            (fortran-find-end-start-end))
        (if (looking-at fortran-block-start-regexp) 
            (setq count (1+ count)))))))

(defun fortran-forward-block-adjust (arg)
  "Execute fortran-forward-block, then adjust the point to the end of the 
preceding line. Serves to leaves block ending constructs visible in hs-node."
  (interactive "p")
  (let ((count (or 1 arg)))
   (fortran-forward-block count)
   (forward-line -1)
   (end-of-line)))

;; Should have a fortran-backward-block for completeness
;; ...

(add-to-list 'hs-special-modes-alist
             `(fortran-mode 
               ,fortran-block-start-regexp
               ,fortran-block-end-regexp
               ,fortran-comment-regexp
               fortran-forward-block-adjust ; forward-sexp-like behavior
               nil
               ))






reply via email to

[Prev in Thread] Current Thread [Next in Thread]