diff --git a/lisp/progmodes/elisp-mode.el b/lisp/progmodes/elisp-mode.el index 7ed2d3d08c..e91d81de6d 100644 --- a/lisp/progmodes/elisp-mode.el +++ b/lisp/progmodes/elisp-mode.el @@ -39,6 +39,7 @@ 'emacs-lisp-mode-abbrev-table (defvar emacs-lisp-mode-syntax-table (let ((table (make-syntax-table lisp-data-mode-syntax-table))) + (modify-syntax-entry ?r "_ p" table) ;; These are redundant, now. ;;(modify-syntax-entry ?\[ "(] " table) ;;(modify-syntax-entry ?\] ")[ " table) diff --git a/src/lread.c b/src/lread.c index a6c2db5d99..8222c17d0b 100644 --- a/src/lread.c +++ b/src/lread.c @@ -2970,10 +2970,11 @@ read1 (Lisp_Object readcharfun, int *pch, bool first_in_list) bool multibyte; char stackbuf[stackbufsize]; current_thread->stack_top = stackbuf; - + bool raw_literal = false; *pch = 0; retry: + raw_literal = false; c = READCHAR_REPORT_MULTIBYTE (&multibyte); if (c < 0) @@ -3564,7 +3565,23 @@ read1 (Lisp_Object readcharfun, int *pch, bool first_in_list) invalid_syntax ("?", readcharfun); } - + /* "raw" string literal syntax, a la Python; "raw" literals do + not process escapes except for \" */ + case 'r': + { + int next_ch; + next_ch = READCHAR; + if (next_ch == '\"') + { + raw_literal = true; + /* fall through to string reading */ + } + else + { + UNREAD (next_ch); + goto read_symbol; + } + } case '"': { ptrdiff_t count = SPECPDL_INDEX (); @@ -3599,7 +3616,21 @@ read1 (Lisp_Object readcharfun, int *pch, bool first_in_list) if (ch == '\\') { int modifiers; - + if (raw_literal) + { + /* still have to handle backslash followed by + double quote even in a raw literal */ + int next_ch = READCHAR; + if (next_ch == '\"') + { + ch = next_ch; + } + else + { + UNREAD(next_ch); + } + goto read_normal_char; + } ch = read_escape (readcharfun, 1); /* CH is -1 if \ newline or \ space has just been seen. */ @@ -3653,6 +3684,7 @@ read1 (Lisp_Object readcharfun, int *pch, bool first_in_list) } else { + read_normal_char: p += CHAR_STRING (ch, (unsigned char *) p); if (CHAR_BYTE8_P (ch)) force_singlebyte = true; diff --git a/test/src/lread-tests.el b/test/src/lread-tests.el index dac8f95bc4..964f3da91b 100644 --- a/test/src/lread-tests.el +++ b/test/src/lread-tests.el @@ -262,5 +262,15 @@ lread-float (should (equal (read "-0.e-5") -0.0)) ) +(ert-deftest lread-string-raw-syntax () + ;; syntax r"a\bc" => string composed of ?a, ?\\, ?b, ?c + (should (equal (read "r\"a\\bc\"") "a\\bc")) + ;; syntax "a\bc" => string composed of ?a, ?\b, ?c + (should (equal (read "\"a\\bc\"") "a\C-hc")) + ;; syntax r"a\"b\"a" => string composed of ?a, ?\", ?b, ?\", ?a + (should (equal (read "r\"a\\\"b\\\"a\"") "a\"b\"a")) + ;; syntax r"a\\b" => string composed of ?a, ?\\, ?\\, ?b + (should (equal (read "r\"a\\\\b\"") "a\\\\b")) + ) ;;; lread-tests.el ends here