当前位置:  开发笔记 > 编程语言 > 正文

如何对使用syntax-parse捕获的可选属性进行分组?

如何解决《如何对使用syntax-parse捕获的可选属性进行分组?》经验,为你挑选了0个好方法。

在编写使用的宏时syntax/parse,我创建了一个拼接语法类,用于捕获可能提供给宏的选项.这些选项都是可选的,它们可以按任何顺序提供.使用~optional省略号头部图案使这很容易:

(define-splicing-syntax-class opts
  (pattern (~seq (~or (~optional (~seq #:a a))
                      (~optional (~seq #:b b))
                      (~optional (~seq #:x x))
                      (~optional (~seq #:y y)))
                 ...))

然而,有一个问题:我希望能够到这些选项分为两组:含组ab,和包含组xy.但是,用户仍可以按任何顺序指定选项,因此对于此示例输入:

(foobar #:b 3 #:y 7 #:a 2)

我希望能够生成以下属性:

first-opts:  (#:a 2 #:b 3)
second-opts: (#:y 7)

到目前为止,我已经设法使用手动执行此操作#:with,但它并不漂亮:

(define-splicing-syntax-class opts
  #:attributes ([first-opts 1] [second-opts 1])
  (pattern (~seq (~or (~optional (~seq #:a a))
                      (~optional (~seq #:b b))
                      (~optional (~seq #:x x))
                      (~optional (~seq #:y y)))
                 ...)
           #:with (first-opts ...)
           #`(#,@(if (attribute a) #'(#:a a) #'())
              #,@(if (attribute b) #'(#:b b) #'()))
           #:with (second-opts ...)
           #`(#,@(if (attribute x) #'(#:x x) #'())
              #,@(if (attribute y) #'(#:y y) #'()))))

这可以简化使用一点点template距离syntax/parse/experimental/template:

(define-splicing-syntax-class opts
  #:attributes ([first-opts 1] [second-opts 1])
  (pattern (~seq (~or (~optional (~seq #:a a))
                      (~optional (~seq #:b b))
                      (~optional (~seq #:x x))
                      (~optional (~seq #:y y)))
                 ...)
           #:with (first-opts ...)
           (template ((?? (?@ #:a a))
                      (?? (?@ #:b b))))
           #:with (second-opts ...)
           (template ((?? (?@ #:a x))
                      (?? (?@ #:b y))))))

但是,这实际上只是上面的一些糖,它实际上并没有解决必须枚举每个子句中的每个选项的问题.例如,如果我添加了一个#:c选项,我需要记住将它添加到first-opts组中,否则它将被完全忽略.

真正想要的是一些声明性的方法来分组这些可选值集.例如,我想要这样的语法:

(define-splicing-syntax-class opts
  #:attributes ([first-opts 1] [second-opts 1])
  (pattern (~seq (~or (~group first-opts
                              (~optional (~seq #:a a))
                              (~optional (~seq #:b b)))
                      (~group second-opts
                              (~optional (~seq #:x x))
                              (~optional (~seq #:y y))))
                 ...)))

或者,更好的是,如果我可以使用现有的原语,这将是很好的,如下所示:

(define-splicing-syntax-class opts
  #:attributes ([first-opts 1] [second-opts 1])
  (pattern (~seq (~or (~and first-opts
                            (~seq (~optional (~seq #:a a))
                                  (~optional (~seq #:b b))))
                      (~and second-opts
                            (~seq (~optional (~seq #:x x))
                                  (~optional (~seq #:y y)))))
                 ...)))

但是,这些都不起作用.有没有办法使用提供的内置提取syntax/parse?如果没有,有没有简单的方法来定义像~group我这样的东西?

推荐阅读
罗文彬2502852027
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有