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
作为宏,它可以只是一个普通函数。这意味着两个变化

  • 定义语法
    更改回
    定义

  • 将函数更改为只接收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,您的回答非常有用。