Function: c-make-keywords-re

c-make-keywords-re is a byte-compiled function defined in cc-defs.el.gz.

Signature

(c-make-keywords-re ADORN LIST &optional MODE)

Documentation

Make a regexp that matches all the strings the list.

Duplicates and nil elements in the list are removed. The resulting regexp may contain zero or more submatch expressions.

If ADORN is t there will be at least one submatch and the first surrounds the matched alternative, and the regexp will also not match a prefix of any identifier. Adorned regexps cannot be appended. The language variable c-nonsymbol-key is used to make the adornment.

A value appendable for ADORN is like above, but all alternatives in the list that end with a word constituent char will have \> appended instead, so that the regexp remains appendable. Note that this variant doesn't always guarantee that an identifier prefix isn't matched since the symbol constituent _ is normally considered a nonword token by \>.

The optional MODE specifies the language to get c-nonsymbol-key from when it's needed. The default is the current language taken from c-buffer-is-cc-mode.

Source Code

;; Defined in /usr/src/emacs/lisp/progmodes/cc-defs.el.gz
(defun c-make-keywords-re (adorn list &optional mode)
  "Make a regexp that matches all the strings the list.
Duplicates and nil elements in the list are removed.  The
resulting regexp may contain zero or more submatch expressions.

If ADORN is t there will be at least one submatch and the first
surrounds the matched alternative, and the regexp will also not match
a prefix of any identifier.  Adorned regexps cannot be appended.  The
language variable `c-nonsymbol-key' is used to make the adornment.

A value `appendable' for ADORN is like above, but all alternatives in
the list that end with a word constituent char will have \\> appended
instead, so that the regexp remains appendable.  Note that this
variant doesn't always guarantee that an identifier prefix isn't
matched since the symbol constituent `_' is normally considered a
nonword token by \\>.

The optional MODE specifies the language to get `c-nonsymbol-key' from
when it's needed.  The default is the current language taken from
`c-buffer-is-cc-mode'."

  (setq list (delete nil (delete-dups list)))
  (if list
      (let (re)

	(if (eq adorn 'appendable)
	    ;; This is kludgy but it works: Search for a string that
	    ;; doesn't occur in any word in LIST.  Append it to all
	    ;; the alternatives where we want to add \>.  Run through
	    ;; `regexp-opt' and then replace it with \>.
	    (let ((unique "") pos)
	      (while (let (found)
		       (setq unique (concat unique "@")
			     pos list)
		       (while (and pos
				   (if (string-match unique (car pos))
				       (progn (setq found t)
					      nil)
				     t))
			 (setq pos (cdr pos)))
		       found))
	      (setq pos (copy-tree list)
		    )
	      (while pos
		(if (string-match "\\w\\'" (car pos))
		    (setcar pos (concat (car pos) unique)))
		(setq pos (cdr pos)))
	      (setq re (regexp-opt list))
	      (setq pos 0)
	      (while (string-match unique re pos)
		(setq pos (+ (match-beginning 0) 2)
		      re (replace-match "\\>" t t re))))

	  (setq re (regexp-opt list)))

	;; Emacs 20 and XEmacs (all versions so far) has a buggy
	;; regexp-opt that doesn't always cope with strings containing
	;; newlines.  This kludge doesn't handle shy parens correctly
	;; so we can't advice regexp-opt directly with it.
	(let (fail-list)
	  (while list
	    (and (string-match "\n" (car list)) ; To speed it up a little.
		 (not (string-match (concat "\\`\\(" re "\\)\\'")
				    (car list)))
		 (setq fail-list (cons (car list) fail-list)))
	    (setq list (cdr list)))
	  (when fail-list
	    (setq re (concat re
			     "\\|"
			     (mapconcat
			      (if (eq adorn 'appendable)
				  (lambda (str)
				    (if (string-match "\\w\\'" str)
					(concat (regexp-quote str)
						"\\>")
				      (regexp-quote str)))
				'regexp-quote)
			      (sort fail-list
				    (lambda (a b)
				      (> (length a) (length b))))
			      "\\|")))))

	;; Add our own grouping parenthesis around re instead of
	;; passing adorn to `regexp-opt', since in XEmacs it makes the
	;; top level grouping "shy".
	(cond ((eq adorn 'appendable)
	       (concat "\\(" re "\\)"))
	      (adorn
	       (concat "\\(" re "\\)"
		       "\\("
		       (c-get-lang-constant 'c-nonsymbol-key nil mode)
		       "\\|$\\)"))
	      (t
	       re)))

    ;; Produce a regexp that doesn't match anything.
    (if adorn
	(concat "\\(" regexp-unmatchable "\\)")
      regexp-unmatchable)))