Создание читаемой таблицы с отключенным макросом диспетчера чтения

Я создаю новый язык, основанный на Racket, и я не хочу определенных #x макросы для работы, такие как синтаксическая кавычка #', Как мне удалить это так, чтобы #' не делает синтаксическую кавычку, но делает то, что делает несвязанный макро-символ отправки?

Я могу сделать это с помощью макросов с одним символом, выполнив

(make-readtable (current-readtable)
                #\' #\a #f) ; set ' to be the same as a normal character

но я не знаю, как это сделать для макроса отправки.

1 ответ

Решение

Предполагая, что вы хотите #' рассматриваться как ':

Обеспечить reader-proc это просто называет нормальным read-syntax:

#lang racket/base

(define (reader-proc ch in src line col pos)
  (read-syntax src in))

(define our-readtable (make-readtable (current-readtable)
                                      #\'
                                      'dispatch-macro
                                      reader-proc))

;; A `#:wrapper1` for `syntax/module-reader`, i.e. to use in your
;; lang/reader.rkt
(define (wrapper1 thk)
  (parameterize ([current-readtable our-readtable])
    (thk)))
(provide wrapper1)

;; tests
(module+ test
  (require rackunit
           racket/port)
  (parameterize ([current-readtable our-readtable])
    (check-equal? (with-input-from-string "#'foo" read)
                  'foo)
    (check-equal? (with-input-from-string "#'(foo)" read)
                  '(foo))
    (check-equal? (with-input-from-string "#'(foo #'(bar))" read)
                  '(foo (bar)))))

Несколько более сложный пример работы с 'dispatch-macro является литеральная поддержка лямбда-ридер, которую я недавно добавил в #lang rackjure,


ОБНОВЛЕНО

Предполагая, что вы хотите #' вызвать ошибку чтения, "bad syntax: #'":

#lang racket/base

(require syntax/readerr)

(define (reader-proc ch in src line col pos)
  (raise-read-error (format "bad syntax: #~a" ch)
                    src line col pos 2))

(define our-readtable (make-readtable (current-readtable)
                                      #\'
                                      'dispatch-macro
                                      reader-proc))

;; A `#:wrapper1` for `syntax/module-reader`, i.e. to use in your
;; lang/reader.rkt
(define (wrapper1 thk)
  (parameterize ([current-readtable our-readtable])
    (thk)))
(provide wrapper1)

;; tests
(module+ test
  (require rackunit
           racket/port)
  (parameterize ([current-readtable our-readtable])
    (check-exn exn:fail? (λ () (with-input-from-string "#'foo" read)))))
Другие вопросы по тегам