概述
您可以使用几种不同的策略,具体取决于最终语法对象的用途 . 特别是,它取决于您是否可以扩展语法以获得具有相同行为的不同语法对象,或者您是否必须完全保留所有内容 .
1.如果最终语法对象用作宏输出中的表达式
如果最终语法对象仅用作宏输出中的表达式,则扩展语法对象很好,因为运行时行为是重要的,而不是语法的确切形式 . 在这种情况下,您可以在包含替换的内部定义上下文中展开语法对象 .
;; create a context where x-old is renamed to x-new
(define ctx (syntax-local-make-definition-context))
(syntax-local-bind-syntaxes
(list x-old)
#`(make-rename-transformer (quote-syntax #,x-new))
ctx)
;; expand the syntax in that context
(local-expand stx 'expression '() ctx)
2.如果最终语法对象应该保持原样,并且无法展开
如果最终语法对象应该保持原样,除了替换,那么你可以't expand it. You have to traverse it somehow to do the substitution. This comes with several problems if the code you'替换为可能使用某些功能,如 quote 或 syntax->datum . 但是,有时候它是必要的,并且有时候我使用带有此签名的 traverse-stx/recur 函数:
;; traverse-stx/recur : Stx [Stx -> Stx] -> Stx
;; Traverses `stx`, calling the `recur` function on every sub-piece
(define (traverse-stx/recur stx recur)
....)
我用的是这样的:
;; stx-subst : Stx Id Id -> Stx
;; Replaces every instance of `x-old` with `x-new` in the syntax `stx`
(define (stx-subst stx x-old x-new)
;; traverse : Stx -> Stx
(define (traverse s)
(cond [(and (identifier? stx) (free-identifier=? stx x-old))
x-new]
[else
;; pass "yourself" as the recur callback, so that it calls
;; you on every sub-piece
(traverse-stx/recur stx traverse)]))
(traverse s))
traverse-stx/recur 的定义可能取决于你的语言're traversing, but if it'字面上只是任意的s-expression而没有"meaning",你害怕改变,那么它的结构就像正常的s-expression遍历一样,尽管 stx-null? , stx-car , stx-cdr 等(来自 syntax/stx 库)而不是正常的 null? , car , cdr 等 .
注意:但是,您为您的语言定义了遍历,这样的辅助函数可能很有用:
;; restore : Stx Any -> Stx
;; Any Any -> Any
(define (restore orig datum)
(if (syntax? orig) (datum->syntax orig datum orig orig) datum))
3.当您需要依赖并保留其他核心语言中的“含义”时
在一些罕见的情况下,可能想要扩展到另一个"core language",而不是完全弄清楚 . 但是,当前策略涉及像(2)那样手动遍历语法对象,同时还使用内部定义上下文(如(1))扩展语法,并在扩展后重构语法 .
到目前为止,我看到的关于如何做到这一点的最佳解释是Blog Post by Alexis King . 但是这很难做到正确,而且你的日子越复杂,它就越难 .
最后
以上就是认真爆米花为你收集整理的java中变量替换_替换语法对象中的变量的全部内容,希望文章能够帮你解决java中变量替换_替换语法对象中的变量所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复