+
+ (defun ruby-syntax-enclosing-percent-literal (limit)
+ (let ((state (syntax-ppss))
+ (start (point)))
+ ;; When already inside percent literal, re-propertize it.
+ (when (eq t (nth 3 state))
+ (goto-char (nth 8 state))
+ (when (looking-at ruby-percent-literal-beg-re)
+ (ruby-syntax-propertize-percent-literal limit))
+ (when (< (point) start) (goto-char start)))))
+
+ (defun ruby-syntax-propertize-percent-literal (limit)
+ (goto-char (match-beginning 2))
+ ;; Not inside a simple string or comment.
+ (when (eq t (nth 3 (syntax-ppss)))
+ (let* ((op (char-after))
+ (ops (char-to-string op))
+ (cl (or (cdr (aref (syntax-table) op))
+ (cdr (assoc op '((?< . ?>))))))
+ parse-sexp-lookup-properties)
+ (condition-case nil
+ (progn
+ (if cl ; Paired delimiters.
+ ;; Delimiter pairs of the same kind can be nested
+ ;; inside the literal, as long as they are balanced.
+ ;; Create syntax table that ignores other characters.
+ (with-syntax-table (make-char-table 'syntax-table nil)
+ (modify-syntax-entry op (concat "(" (char-to-string cl)))
+ (modify-syntax-entry cl (concat ")" ops))
+ (modify-syntax-entry ?\\ "\\")
+ (save-restriction
+ (narrow-to-region (point) limit)
+ (forward-list))) ; skip to the paired character
+ ;; Single character delimiter.
+ (re-search-forward (concat "[^\\]\\(?:\\\\\\\\\\)*"
+ (regexp-quote ops)) limit nil))
+ ;; Found the closing delimiter.
+ (put-text-property (1- (point)) (point) 'syntax-table
+ (string-to-syntax "|")))
+ ;; Unclosed literal, leave the following text unpropertized.
+ ((scan-error search-failed) (goto-char limit))))))
+
+ (defun ruby-syntax-propertize-expansions (start end)
+ (remove-text-properties start end '(ruby-expansion-match-data))
+ (goto-char start)
+ ;; Find all expression expansions and
+ ;; - save the match data to a text property, for font-locking later,
+ ;; - set the syntax of all double quotes and backticks to punctuation.
+ (while (re-search-forward ruby-expression-expansion-re end 'move)
+ (let ((beg (match-beginning 2))
+ (end (match-end 2)))
+ (when (and beg (save-excursion (nth 3 (syntax-ppss beg))))
+ (put-text-property beg (1+ beg) 'ruby-expansion-match-data
+ (match-data))
+ (goto-char beg)
+ (while (re-search-forward "[\"`]" end 'move)
+ (put-text-property (match-beginning 0) (match-end 0)
+ 'syntax-table (string-to-syntax ".")))))))