首页 > 解决方案 > 如何匹配球拍中的语法?

问题描述

我想编写一个与给定语法是否匹配的宏 a ifor cond,我尝试像这样编写它:

(define-syntax (foo stx)
  (syntax-case stx ()
    [(_ (if a b)) #'"if!"] 
    [(_ (cond a b) #'"cond!"]))

但它总是匹配第一种情况。如何区分这两种情况?

标签: racket

解决方案


syntax-case模式中,标识符匹配任何内容。您已经假设这是真的:当您编写模式时(if a b),大概您假设a将匹配任何语法,而不仅仅是文字标识符a。标识符也是如此if——您实际上并没有检查标识符是否为if,您只是匹配任何语法并将其绑定到名为 的模式变量if

这就是文字列表的用途。当您将标识符放在文字列表中时,它会告诉syntax-case您检查该特定标识符而不是绑定模式变量。所以你可能想要这个,而不是:

(define-syntax (foo stx)
  (syntax-case stx (if cond)
    [(_ (if a b)) #'"if!"] 
    [(_ (cond a b) #'"cond!"]))

但是,请注意,它syntax-case已经很老了,而且 Racket 已经提供了一个更好的语法匹配库近十年了,syntax/parse. 我会syntax-case在所有情况下都推荐它。上述宏的syntax/parse等效项如下所示:

(require (for-syntax syntax/parse))

(define-syntax (foo stx)
  (syntax-parse stx
    #:literals [if cond]
    [(_ (if a b)) #'"if!"] 
    [(_ (cond a b) #'"cond!"]))

……基本一样,但是syntax-parse的模式语言比 . 丰富得多syntax-case。例如,如果您想省略#:literals声明,您可以使用以下方法注释各个文字模式~literal

(define-syntax (foo stx)
  (syntax-parse stx
    [(_ ((~literal if) a b)) #'"if!"] 
    [(_ ((~literal cond) a b) #'"cond!"]))

有关详细信息,请参阅syntax/parse.


推荐阅读