raw-strings.scm 1.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253
  1. ; -*- mode: scheme; coding: utf-8 -*-
  2. ;; Reader extension for raw strings
  3. ;; by lloda@sarc.name 2017, 2019, 2022
  4. ;; This code is in the public domain.
  5. ;; Based on R"delimiter(raw_characters)delimiter"
  6. ;; in http://en.cppreference.com/w/cpp/language/string_literal.
  7. ;; Having #R, the quotes are unnecessary, so I consider them part of the delimiter;
  8. ;; you can ellide them.
  9. (define-module (raw-strings)
  10. #:use-module ((ice-9 rdelim)))
  11. ; configuration.
  12. (eval-when (expand load eval)
  13. (define openc "([\"")
  14. (define closec ")]\"")
  15. (define extension-char #\R))
  16. (define (reader-extension-raw-string chr port)
  17. (define (char-please port)
  18. (let ((c (read-char port)))
  19. (if (eof-object? c)
  20. (throw 'end-of-file-reading-raw-string)
  21. c)))
  22. (let* ((fix-open (read-delimited openc port 'split))
  23. (fix (car fix-open))
  24. (open (cdr fix-open))
  25. (close
  26. (let-syntax ((pick-close
  27. (lambda (stx)
  28. (syntax-case stx ()
  29. ((_ o)
  30. #`(case o
  31. #,@(map (lambda (a b) `((,a) ,b))
  32. (string->list openc) (string->list closec))
  33. (else (throw 'raw-string-delimiter-not-found fix))))))))
  34. (pick-close open))))
  35. (when (string-index fix char-whitespace?)
  36. (throw 'raw-string-delimiter-has-whitespace fix))
  37. (let search-delim ((c (char-please port)) (s '()))
  38. (if (eqv? close c)
  39. (let search-close ((ss (list close)) (i 0))
  40. (if (= i (string-length fix))
  41. (list->string (reverse! s))
  42. (let ((c (char-please port)))
  43. (if (eqv? (string-ref fix i) c)
  44. (search-close (cons c ss) (+ 1 i))
  45. (search-delim c (append ss s))))))
  46. (search-delim (char-please port) (cons c s))))))
  47. (read-hash-extend extension-char reader-extension-raw-string)