 
   (unless pos
     (setq pos (point)))
-  (if (= pos 1)
-      nil
-    (when (> pos go-mode-mark-cs-end)
-      (go-mode-mark-cs pos))
-    (get-text-property (- pos 1) 'go-mode-cs)))
+  (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
-   (let* ((pos go-mode-mark-cs-end)
-          (state (or go-mode-mark-cs-state (syntax-ppss pos))))
-     ;; Mark comments and strings
-     (when (nth 8 state)
-       ;; Get to the beginning of the comment/string
-       (setq pos (nth 8 state)
-             state nil))
-     (while (> end pos)
-       ;; Find beginning of comment/string
-       (while (and (> end pos)
-                   (progn
-                     (setq state (parse-partial-sexp pos end nil nil state 'syntax-table)
-                           pos (point))
-                     (not (nth 8 state)))))
-       ;; Find end of comment/string
-       (let ((start (nth 8 state)))
-         (when start
-           (setq state (parse-partial-sexp pos (point-max) nil nil state 'syntax-table)
-                 pos (point))
-           ;; Mark comment
-           (put-text-property start (- pos 1) 'go-mode-cs (cons start pos))
-           (when nil
-             (put-text-property start (- pos 1) 'face
-                                `((:background "midnight blue")))))))
-     ;; Update state
-     (setq go-mode-mark-cs-end   pos
-           go-mode-mark-cs-state state))))
+   (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

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))))

               (progn ,@body)
             (set-buffer-modified-p ,modified-var)))))))

(defun go-mode-cs (&optional pos)
  "Return the comment/string state at point POS.  If point is
inside a comment or string (including the delimiters), this
returns a pair (START . END) indicating the extents of the
