匹配可选模式并绑定属性的拼接语法类 [英] A splicing syntax class that matches an optional pattern and binds attributes
问题描述
我所拥有的一个拼接语法类定义如下.语法类匹配两个语句的序列(第一个模式),其中一个语句(第三个和第二个模式),甚至可能根本不匹配这些语句(最后一个模式).
A splicing syntax class that I have is defined as follows. The syntax class matches a sequence of two statements (first pattern), one of the statements (third and second patterns) and perhaps even none of those statements at all (last pattern).
正如你所看到的,有很多重复"的代码,因为每个模式要么返回模式中捕获的某些东西的属性,要么返回一个空的东西.我的问题是目前该语句从来都不是真正可选的,因为最后一个模式必须匹配某些内容.在这种情况下,一组空的括号 ()
.
As you can see there is quite a lot of "duplicate" code, because every pattern returns either the attributes of something captured in the pattern, or an empty thing otherwise. The problem I have is that currently the statement is never truly optional, since the last pattern must match something. In this case an empty set of brackets ()
.
问题是:我怎样才能使语句真正可选?作为一个附带问题 - 可以通过更好地利用头部模式来压缩代码吗?
The question is: how can I make the statement truly optional? As a side question - can the code be condensed by making better use of head patterns?
(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 ...) #'()))
推荐答案
听起来你有两个独立的东西,两者都是可选的.所以有两个单独的语法类是有意义的,就像这样:
It sounds like you have two separate things, both of which are optional. So it makes sense to have two separate syntax-classes, like this:
(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 个术语的 ()
.然后可以像这样定义一个类似于你原来的语法类:
Both of these use an empty (~seq)
case (matches 0 terms) to make it optional, instead of ()
, which matches 1 term. Then a syntax-class similar to your original one can be defined like this:
(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 个术语,当两个选项都不存在时,它必须是 ()
.
This is different from your original one because this can match 0, 1, or 2 terms, while yours will require at least 1 term, which will have to be ()
when neither option is present.
这篇关于匹配可选模式并绑定属性的拼接语法类的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!