使用禁用的调度读取器宏创建可读表

时间:2014-03-12 03:35:32

标签: macros racket reader-macro

我正在创建一种基于Racket的新语言,我不希望某些#x宏工作,例如syntax-quote #'。我如何删除它以便#'不进行语法引用,但是对于未绑定的分派宏char来做什么?

我可以通过

使用单字符宏来实现
(make-readtable (current-readtable)
                #\' #\a #f) ; set ' to be the same as a normal character

但我不知道如何为调度宏执行此操作。

1 个答案:

答案 0 :(得分:0)

假设您希望将#'视为'

提供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的一个稍微复杂的例子是lambda reader literal support I just recently added#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)))))