     (modify-syntax-entry ?<  "." st)
     (modify-syntax-entry ?>  "." st)
 
-    ;; Strings
-    (modify-syntax-entry ?\" "\"" st)
-    (modify-syntax-entry ?\' "\"" st)
-    (modify-syntax-entry ?`  "\"" st)
-    (modify-syntax-entry ?\\ "\\" st)
-
-    ;; Comments
-    (modify-syntax-entry ?/  ". 124b" st)
-    (modify-syntax-entry ?*  ". 23"   st)
-    (modify-syntax-entry ?\n "> b"    st)
-    (modify-syntax-entry ?\^m "> b"   st)
+    ;; Strings and comments are font-locked separately.
+    (modify-syntax-entry ?\" "." st)
+    (modify-syntax-entry ?\' "." st)
+    (modify-syntax-entry ?`  "." st)
+    (modify-syntax-entry ?\\ "." st)
 
     st)
   "Syntax table for Go mode.")

to and including character (1- go-mode-mark-cs-end)).")
(make-variable-buffer-local 'go-mode-mark-cs-end)

(defvar go-mode-mark-cs-state nil
  "The `parse-partial-sexp' state of the comment/string parser as
of the point `go-mode-mark-cs-end'.")
(make-variable-buffer-local 'go-mode-mark-cs-state)

(defvar go-mode-mark-nesting-end 1
  "The point at which the nesting cache ends.  The buffer will be
marked from the beginning up to this point.")
(make-variable-buffer-local 'go-mode-mark-nesting-end)

(defun go-mode-mark-clear-cache (b e l)
  "An after-change-function that clears the comment/string and
nesting caches from the modified point on."

  (save-restriction
    (widen)
    (when (< b go-mode-mark-cs-end)
      (remove-text-properties b (min go-mode-mark-cs-end (point-max)) '(go-mode-cs nil))
      (setq go-mode-mark-cs-end b
            go-mode-mark-cs-state nil))

    (when (< b go-mode-mark-nesting-end)
      (remove-text-properties b (min go-mode-mark-nesting-end (point-max)) '(go-mode-nesting nil))
      (setq go-mode-mark-nesting-end b))))


  (unless pos
    (setq pos (point)))
  (when (> pos go-mode-mark-cs-end)
    (go-mode-mark-cs pos))
  (get-text-property pos 'go-mode-cs))

(defun go-mode-mark-cs (end)
  "Mark comments and strings up to point END.  Don't call this
directly; use `go-mode-cs'."
  (setq end (min end (point-max)))
  (go-mode-parser
   (save-match-data
     (let ((pos
	    ;; Back up to the last known state.
	    (let ((last-cs
		   (and (> go-mode-mark-cs-end 1)
			(get-text-property (1- go-mode-mark-cs-end) 
					   'go-mode-cs))))
	      (if last-cs
		  (car last-cs)
		(max 1 (1- go-mode-mark-cs-end))))))
       (while (< pos end)
	 (goto-char pos)
	 (let ((cs-end			; end of the text property
		(cond
		 ((looking-at "//")
		  (end-of-line)
		  (point))
		 ((looking-at "/\\*")
		  (goto-char (+ pos 2))
		  (if (search-forward "*/" (1+ end) t)
		      (point)
		    end))
		 ((looking-at "\"")
		  (goto-char (1+ pos))
		  (if (looking-at "[^\"\n\\\\]*\\(\\\\.[^\"\n\\\\]*\\)*\"")
		      (match-end 0)
		    (end-of-line)
		    (point)))
		 ((looking-at "'")
		  (goto-char (1+ pos))
		  (if (looking-at "[^'\n\\\\]*\\(\\\\.[^'\n\\\\]*\\)*'")
		      (match-end 0)
		    (end-of-line)
		    (point)))
		 ((looking-at "`")
		  (goto-char (1+ pos))
		  (while (if (search-forward "`" end t)
			     (if (eq (char-after) ?`)
				 (goto-char (1+ (point))))
			   (goto-char end)
			   nil))
		  (point)))))
	   (cond
	    (cs-end
	     (put-text-property pos cs-end 'go-mode-cs (cons pos cs-end))
	     (setq pos cs-end))
	    ((re-search-forward "[\"'`]\\|/[/*]" end t)
	     (setq pos (match-beginning 0)))
	    (t
	     (setq pos end)))))
       (setq go-mode-mark-cs-end pos)))))



(defun go-mode-font-lock-cs (limit comment)
  "Helper function for highlighting comment/strings.  If COMMENT is t,
set match data to the next comment after point, and advance point
after it.  If COMMENT is nil, use the next string.  Returns nil
if no further tokens of the type exist."
  ;; Ensures that `next-single-property-change' below will work properly.
  (go-mode-cs limit)
  (let (cs next (result 'scan))
    (while (eq result 'scan)
      (if (or (>= (point) limit) (eobp))
	  (setq result nil)
	(setq cs (go-mode-cs))
	(if cs
	    (if (eq (= (char-after (car cs)) ?/) comment)
		;; If inside the expected comment/string, highlight it.
		(progn
		  ;; If the match includes a "\n", we have a
		  ;; multi-line construct.  Mark it as such.
		  (goto-char (car cs))
		  (when (search-forward "\n" (cdr cs) t)
		    (put-text-property
		     (car cs) (cdr cs) 'font-lock-multline t))
		  (set-match-data (list (car cs) (cdr cs) (current-buffer)))
		  (goto-char (cdr cs))
		  (setq result t))
	      ;; Wrong type.  Look for next comment/string after this one.
	      (goto-char (cdr cs)))
	  ;; Not inside comment/string.  Search for next comment/string.
	  (setq next (next-single-property-change
		      (point) 'go-mode-cs nil limit))
	  (if (and next (< next limit))
	      (goto-char next)
	    (setq result nil)))))
    result))

(defun go-mode-font-lock-cs-string (limit)
  "Font-lock iterator for strings."
  (go-mode-font-lock-cs limit nil))

(defun go-mode-font-lock-cs-comment (limit)
  "Font-lock iterator for comments."
  (go-mode-font-lock-cs limit t))

(defsubst go-mode-nesting (&optional pos)
  "Return the nesting at point POS.  The nesting is a list
