Function: sgml-parse-tag-backward
sgml-parse-tag-backward is a byte-compiled function defined in
sgml-mode.el.gz.
Signature
(sgml-parse-tag-backward &optional LIMIT)
Documentation
Parse an SGML tag backward, and return information about the tag.
Assume that parsing starts from within a textual context. Leave point at the beginning of the tag.
Source Code
;; Defined in /usr/src/emacs/lisp/textmodes/sgml-mode.el.gz
(defun sgml-parse-tag-backward (&optional limit)
"Parse an SGML tag backward, and return information about the tag.
Assume that parsing starts from within a textual context.
Leave point at the beginning of the tag."
(catch 'found
(let (tag-type tag-start tag-end name)
(or (sgml--find-<>-backward limit)
(error "No tag found"))
(when (eq (char-after) ?<)
;; Oops!! Looks like we were not in a textual context after all!.
;; Let's try to recover.
;; Remember the tag-start so we don't need to look for it later.
;; This is not just an optimization but also makes sure we don't get
;; stuck in infloops in cases where "looking back for <" would not go
;; back far enough.
(setq tag-start (point))
(with-syntax-table sgml-tag-syntax-table
(let ((pos (point)))
(condition-case nil
;; FIXME: This does not correctly skip over PI and CDATA tags.
(sgml-forward-sexp 1)
(scan-error
;; This < seems to be just a spurious one, let's ignore it.
(goto-char pos)
(throw 'found (sgml-parse-tag-backward limit))))
;; Check it is really a tag, without any extra < or > inside.
(unless (sgml-tag-text-p pos (point))
(goto-char pos)
(throw 'found (sgml-parse-tag-backward limit)))
(forward-char -1))))
(setq tag-end (1+ (point)))
(cond
((sgml-looking-back-at "--") ; comment
(setq tag-type 'comment
tag-start (or tag-start (search-backward "<!--" nil t))))
((sgml-looking-back-at "]]") ; cdata
(setq tag-type 'cdata
tag-start (or tag-start
(re-search-backward "<!\\[[A-Z]+\\[" nil t))))
((sgml-looking-back-at "?") ; XML processing-instruction
(setq tag-type 'pi
;; IIUC: SGML processing instructions take the form <?foo ...>
;; i.e. a "normal" tag, handled below. In XML this is changed
;; to <?foo ... ?> where "..." can contain < and > and even <?
;; but not ?>. This means that when parsing backward, there's
;; no easy way to make sure that we find the real beginning of
;; the PI.
tag-start (or tag-start (search-backward "<?" nil t))))
(t
(unless tag-start
(setq tag-start
(with-syntax-table sgml-tag-syntax-table
(goto-char tag-end)
(condition-case nil
(sgml-forward-sexp -1)
(scan-error
;; This > isn't really the end of a tag. Skip it.
(goto-char (1- tag-end))
(throw 'found (sgml-parse-tag-backward limit))))
(point))))
(goto-char (1+ tag-start))
(pcase (char-after)
(?! (setq tag-type 'decl)) ; declaration
(?? (setq tag-type 'pi)) ; processing-instruction
(?% (setq tag-type 'jsp)) ; JSP tags
(?/ ; close-tag
(forward-char 1)
(setq tag-type 'close
name (sgml-parse-tag-name)))
(_ ; open or empty tag
(setq tag-type 'open
name (sgml-parse-tag-name))
(if (or (eq ?/ (char-before (- tag-end 1)))
(sgml-empty-tag-p name))
(setq tag-type 'empty))))))
(goto-char tag-start)
(sgml-make-tag tag-type tag-start tag-end name))))