使用 hygenic 宏展平语法树
Flatten syntax tree using hygenic macros
是否可以编写一个 R5RS 宏来“展平”任意深度的语法树?
示例:
(flatten-syntax (a (b (c d)) e)) => (a b c d e)
我的最终目标是拥有另一个像这样工作的宏:
(declare-tree (a (b (c d)) e))
=>
(begin (define a #f) (define b #f) (define c #f) (define d #f) (define e #f))
但如果 flatten-syntax
可用,应该很容易定义。
这里对我来说最具挑战性的部分是 syntax-rules
-only 限制,但如果您有 syntax-case
解决方案,请也 post 它。
我在这个问题上的进展停滞在这一点上:
(define-syntax flatten-syntax-helper
(syntax-rules ()
((_ buf (x . xs))
(flatten-syntax-helper
(flatten-syntax-helper buf x) xs))
((_ buf ())
buf)
((_ buf x)
(x . buf))))
(define-syntax-rule (my-flatten-syntax T)
(flatten-syntax-helper () T))
在 guile
中,,expand (my-flatten-syntax (a (b (c d)) e))
导致语法错误“无法匹配 my-flatten-syntax 形式的任何模式”。
这是我的快速尝试:
#lang racket
(define-syntax reverse-macro
(syntax-rules ()
[(_ () (result ...)) '(result ...)]
[(_ (x xs ...) (result ...)) (reverse-macro (xs ...) (x result ...))]))
(define-syntax flatten-syntax-aux
(syntax-rules ()
[(_ ((xs ...) ys ...) (result ...))
(flatten-syntax-aux (xs ... ys ...) (result ...))]
[(_ (x xs ...) (result ...))
(flatten-syntax-aux (xs ...) (x result ...))]
[(_ () (result ...))
(reverse-macro (result ...) ())]))
(define-syntax-rule (flatten-syntax xs)
(flatten-syntax-aux xs ()))
(flatten-syntax (a (b (c d)) e)) ;=> '(a b c d e)
确实,您可以通过稍微调整 flatten-syntax
来创建 declare-tree
,但您可能会感到惊讶,直接定义 declare-tree
实际上要容易得多:
#lang racket
(define-syntax declare-tree
(syntax-rules ()
[(_ ((xs ...) ys ...))
(begin (declare-tree (xs ...))
(declare-tree (ys ...)))]
[(_ (x xs ...))
(begin (define x #f)
(declare-tree (xs ...)))]
[(_ ())
(begin)]))
(declare-tree (a (b (c d)) e))
(list a b c d e) ;=> '(#f #f #f #f #f)
这是因为declare-tree
其实不需要展平结构。它可以生成嵌套的begin
,如:
(begin
(begin (define a #f)
(define b #f))
(begin (define c #f)
(define d #f)))
是否可以编写一个 R5RS 宏来“展平”任意深度的语法树?
示例:
(flatten-syntax (a (b (c d)) e)) => (a b c d e)
我的最终目标是拥有另一个像这样工作的宏:
(declare-tree (a (b (c d)) e))
=>
(begin (define a #f) (define b #f) (define c #f) (define d #f) (define e #f))
但如果 flatten-syntax
可用,应该很容易定义。
这里对我来说最具挑战性的部分是 syntax-rules
-only 限制,但如果您有 syntax-case
解决方案,请也 post 它。
我在这个问题上的进展停滞在这一点上:
(define-syntax flatten-syntax-helper
(syntax-rules ()
((_ buf (x . xs))
(flatten-syntax-helper
(flatten-syntax-helper buf x) xs))
((_ buf ())
buf)
((_ buf x)
(x . buf))))
(define-syntax-rule (my-flatten-syntax T)
(flatten-syntax-helper () T))
在 guile
中,,expand (my-flatten-syntax (a (b (c d)) e))
导致语法错误“无法匹配 my-flatten-syntax 形式的任何模式”。
这是我的快速尝试:
#lang racket
(define-syntax reverse-macro
(syntax-rules ()
[(_ () (result ...)) '(result ...)]
[(_ (x xs ...) (result ...)) (reverse-macro (xs ...) (x result ...))]))
(define-syntax flatten-syntax-aux
(syntax-rules ()
[(_ ((xs ...) ys ...) (result ...))
(flatten-syntax-aux (xs ... ys ...) (result ...))]
[(_ (x xs ...) (result ...))
(flatten-syntax-aux (xs ...) (x result ...))]
[(_ () (result ...))
(reverse-macro (result ...) ())]))
(define-syntax-rule (flatten-syntax xs)
(flatten-syntax-aux xs ()))
(flatten-syntax (a (b (c d)) e)) ;=> '(a b c d e)
确实,您可以通过稍微调整 flatten-syntax
来创建 declare-tree
,但您可能会感到惊讶,直接定义 declare-tree
实际上要容易得多:
#lang racket
(define-syntax declare-tree
(syntax-rules ()
[(_ ((xs ...) ys ...))
(begin (declare-tree (xs ...))
(declare-tree (ys ...)))]
[(_ (x xs ...))
(begin (define x #f)
(declare-tree (xs ...)))]
[(_ ())
(begin)]))
(declare-tree (a (b (c d)) e))
(list a b c d e) ;=> '(#f #f #f #f #f)
这是因为declare-tree
其实不需要展平结构。它可以生成嵌套的begin
,如:
(begin
(begin (define a #f)
(define b #f))
(begin (define c #f)
(define d #f)))