Racket 宏语法大小写匹配列表
我试图创建宏,从输入列表生成一些代码。但在我的语法案例中,我无法匹配它 示例代码:Racket 宏语法大小写匹配列表,racket,Racket,我试图创建宏,从输入列表生成一些代码。但在我的语法案例中,我无法匹配它 示例代码: #lang racket/base (require (for-syntax racket/base)) (define test-data '(root () (branch ((name "left")) (leaf ((name "green0"))) (leaf ((name "yellow"))) (leaf ((
#lang racket/base
(require (for-syntax racket/base))
(define test-data '(root
()
(branch ((name "left")) (leaf ((name "green0"))) (leaf ((name "yellow"))) (leaf ((name "pink"))))
(branch ((name "right")) (leaf ((name "name2"))))
(branch ((name "broken")))))
(define-syntax (parse-xml stx)
(syntax-case stx (root branch)
[(_ (root () branches ...))
#'branches...
]
[(_ rest) #'rest]))
(parse-xml (datum->syntax #'() test-data))
我觉得我缺少了一些非常基本的东西,但我不知道如何将输入参数“扩展”到stx中以使其匹配。你能帮我吗?
提前感谢您。如果您想在运行时解析它
您不需要将解析xml
作为宏,它可以只是一个普通函数。这意味着两个变化
定义语法
更改回定义
(define (parse-xml xml)
(syntax-case xml (root branch)
[(root () branches ...) ; notice how the pattern changed for (2)
#'branches...
]
[rest #'rest]))
尸体还没完工,我想你可以从这里拿走
如果您想在编译时解析它
根据您的评论,用户会这样使用它:
(parse-xml/file "path/to/data.xml")
那么宏不应该采用像test data
这样的变量,它应该采用文件路径
(require (for-syntax racket/base))
(define-syntax parse-xml/file
(lambda (stx)
(syntax-case stx ()
[(_ file-path)
....
])))
接下来要做的是找到要读取的文件。我找到的解析宏路径的最佳方法是syntax/path spec
中的resolve path spec
(require (for-syntax racket/base
syntax/path-spec))
(define-syntax parse-xml/file
(lambda (stx)
(syntax-case stx ()
[(_ file-path)
(.... (resolve-path-spec #'file-path #'file-path stx) ....)])))
下一步是从中读取,可能使用openinput file
和语法:从xml
读取xml
(require (for-syntax racket/base
syntax/path-spec
xml))
(define-syntax parse-xml/file
(lambda (stx)
(syntax-case stx ()
[(_ file-path)
(....
(syntax:read-xml
(open-input-file (resolve-path-spec #'file-path #'file-path stx)))
....)])))
此时,您有一个语法对象,由syntax:readxml
生成,包含数据
现在,如果您想在运行时解析函数,我们可以从部分返回该函数。要在编译时使用它,只需将定义放入语法的begin
(require (for-syntax racket/base
syntax/path-spec
xml))
(begin-for-syntax
(define (parse-xml xml)
(syntax-case (xml->xexpr
((eliminate-whitespace '(root branch name leaf))
(document-element xml))) (root branch)
[(root () branches ...)
#''(branches ...)
]
[rest #'rest])))
(define-syntax parse-xml/file
(lambda (stx)
(syntax-case stx ()
[(_ file-path)
(parse-xml
(read-xml
(open-input-file (resolve-path-spec #'file-path #'file-path stx))))
])))
剩下的就是完成函数版本的
parse xml
来解析它并生成代码。您能帮点忙吗?按照现在的方式,parse xml
是一个宏,在编译时运行,但是test data
的值只有在运行时才知道。您是想在编译时解析xml文件,还是只需要在运行时解析它?我需要resd.xml文件并从中生成dbus接口:所以我想如果可能的话,.xml文件也应该在编译时被resd。好的。那么,“用户”将如何使用解析xml
?这会影响宏的编写方式。这应该是“helper”的乐趣,但我希望用户调用st.like(生成dbus接口“org.freedesktop.Notifications.xml”)xml描述dbus消息的格式(),应该从该格式生成此源代码:(定义dbus接口通知“org.freedesktop.Notifications”)(CloseNotification“u”)(GetCapabilities“”)(GetServerInformation“”)(Notify“sussasa{sv}i”))
这意味着解析它获取方法名称和类型,将类型连接到字符串并输出interfaHere是一个通知发送的工作示例:我希望根据此xml自动生成第11-15行:非常感谢Alex,您的回答非常有用。