A splicing syntax class that matches an optional pattern and binds attributes
Asked Answered
B

1

4

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   ...) #'()))
Bedew answered 13/2, 2016 at 18:21 Comment(0)
B
5

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    ...) #'()])

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)])

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.

Belsky answered 13/2, 2016 at 19:5 Comment(3)
As a comment, in signal-subscriptions-and-declarations you need to name the subscriptions and declarations pattern variables, and have a #:with clause for everything you want to provide to users of the class (from the subscriptions and declarations variables)Bedew
Oh, sorry, I meant to include #:auto-nested-attributes, which is another way of doing that.Belsky
Did not know about that. Cool. Thanks!Bedew

© 2022 - 2024 — McMap. All rights reserved.