拼接语法类,它匹配可选模式并绑定属性

时间:2016-02-13 18:21:38

标签: racket

我所拥有的拼接语法类定义如下。语法类匹配两个语句(第一个模式)的序列,一个语句(第三个和第二个模式),甚至根本不匹配任何语句(最后一个模式)。

正如您所看到的,存在相当多的“重复”代码,因为每个模式都返回模式中捕获的内容的属性,否则返回空的内容。我遇到的问题是,当前语句永远不是真正可选的,因为最后一个模式必须匹配某些东西。在这种情况下,一组空括号()

问题是:如何使声明真正可选?作为一个附带问题 - 可以通过更好地利用头部模式来缩小代码吗?

(define-splicing-syntax-class signal-subscriptions-and-declarations
  #:description "subscriptions to signals and signal declarations"

  ; Match the case where both a subscription and declaration statement is present
  (pattern (~seq subscribed:signal-subscriptions  declared:signal-declarations)
           #:with (subscription-collection  ...) #'(subscribed.signal-collection ...)
           #:with (subscription-signal-id   ...) #'(subscribed.signal-identifier ...)
           #:with (declaration-signal-id    ...) #'(declared.signal-identifier ...))

  ; Match the case where no declaration statement is present
  (pattern subscribed:signal-subscriptions
           #:with (subscription-collection ...) #'(subscribed.signal-collection ...)
           #:with (subscription-signal-id  ...) #'(subscribed.signal-identifier ...)
           #:with (declaration-signal-id   ...) #'())

  ; Match the case where no subscription statement is present
  (pattern declared:signal-declarations
           #:with (subscription-collection ...) #'()
           #:with (subscription-signal-id  ...) #'()
           #:with (declaration-signal-id   ...) #'(declared.signal-identifier ...))

  (pattern ()
           #:with (subscription-collection ...) #'()
           #:with (subscription-signal-id  ...) #'()
           #:with (declaration-signal-id   ...) #'()))

1 个答案:

答案 0 :(得分:4)

听起来你有两个不同的东西,两者都是可选的。所以有两个单独的语法类是有意义的,比如:

(define-splicing-syntax-class opt-signal-subscriptions
  ;; Match the case where a subscription is present
  [pattern (~seq subscribed:signal-subscriptions)
           #:with (subscription-collection  ...) #'(subscribed.signal-collection ...)
           #:with (subscription-signal-id   ...) #'(subscribed.signal-identifier ...)]
  ;; Match the case where no subscription is present
  [pattern (~seq)
           #:with (subscription-collection  ...) #'()
           #:with (subscription-signal-id   ...) #'()])

(define-splicing-syntax-class opt-signal-declarations
  ;; Match the case where a declaration statement is present
  [pattern (~seq declared:signal-declarations)
           #:with (declaration-signal-id    ...) #'(declared.signal-identifier ...)]
  ;; Match the case where no declaration statement is present
  [pattern (~seq)
           #:with (declaration-signal-id    ...) #'()])

这两个案例都使用空(~seq)案例(匹配0个术语)使其成为可选项,而不是(),它匹配1个术语。然后可以像这样定义类似于原始语法类的语法类:

(define-splicing-syntax-class signal-subscriptions-and-declarations
  #:description "subscriptions to signals and signal declarations"
  #:auto-nested-attributes
  [pattern (~seq :opt-signal-subscriptions :opt-signal-declarations)])

这与原始版本不同,因为它可以匹配0,1或2个术语,而您的术语至少需要1个术语,当两个术语都不存在时,该术语必须为()