宏语法大小写匹配列表

时间:2017-12-14 12:55:19

标签: racket

我正在尝试创建宏,从输入列表生成一些代码。但我在语法案例中无法与之匹配。

示例代码:

#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是可匹配的。你能帮帮我吗? 提前谢谢。

1 个答案:

答案 0 :(得分:1)

如果要在运行时解析它

你不需要parse-xml成为一个宏,它只是一个正常的功能。这意味着两个变化。

  1. define-syntax更改回define

  2. 将函数更改为仅接收xml内容的帐户,而不是整个"宏"表达

  3. 改变这两个结果

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

    接下来要做的是找到要读取的文件。我找到的解析宏路径的最佳方式是来自resolve-path-spec的{​​{1}}。

    syntax/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) ....)]))) 中的open-input-filesyntax:read-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:read-xml

    begin-for-syntax

    剩下的就是完成(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)))) ]))) 功能版本来解析它并生成代码。