0

我有一个需要等价的情况,例如:

[
    {Foo}
    http://example.com/some/stuff.html
    separator
]

...就像你写的那样处理:

[
    [{Foo}]
    [http://example.com/some/stuff.html]
    [separator]
]

增加一点复杂性的是,如果您将项目放在一个块中,那么它可以有参数:

[
    [{Foo} /some-refinement]
    [http://example.com/some/stuff.html {stuff caption} 3]
    [separator dashed-line]
]

我想要一个基于 PARSE 的引擎,它可以为 、 和 (我们称之为 STRING-HANDLER) 运行相同的处理程序{Foo}[{Foo}]并且[{Foo} /some-refinement] 只需使用正确数量的参数调用它。

在没有 PARSE 的情况下编写这个很容易......单个元素被包装在一个临时块中(如果它不是一个块)。然后在 CASE 语句中测试第一项。但我想将其转换为基于 PARSE 的,其中一个分支使用 INTO 而另一个不使用,无需重复代码。

它需要支持嵌套,因此您可能最终会处理以下内容:

[http://example.com/some/stuff.html [{Foo} /some-refinement] 3]
4

1 回答 1

1

我希望以下内容可以成为您解决问题的基础。

以下在 R2 和 R3 中的执行完全相同。PARSE 的运行在两者之间非常不同,因此我放置了一个简单的保护[.here.: block! :.here.]程序来修复两个平台中不同的错误情况。

我使用了钩子函数,可以将数据浏览与数据评估完全分开。如果您仔细观察,您会注意到 =enter-block?=: 规则是全局的,并且切换其含义的代码是在运行 emit-value 函数之前设置的......所以在某些情况下,您可能实际上想要使用 emit-value 设置不同的规则。

请注意,我没有假设任何已知的结构,因为您的解释似乎是针对非结构化数据集的。

另请注意,测试 B 设置为字符串,因此我们可以直接在字符串输入数据上使用包装器:

rebol [
    author: "Maxim Olivier-Adlhoch"
    date: 2014-02-08
    license: "public domain"
]


A: [
    [{Foo}]
    [http://example.com/some/stuff.html]
    [separator]
]


B: {[
    {Foo}
    http://example.com/some/stuff.html
    separator
]}


C: [
    [{Foo} /some-refinement]
    [http://example.com/some/stuff.html {stuff caption} 3]
    [separator dashed-line]
]


D: [http://example.com/some/stuff.html [{Foo} /some-refinement] 3]


depth: ""
enter-block: func [][
    prin depth 
    print "[" 
    append depth "^-"
]

quit-block: func [][
    remove depth 
    prin depth 
    print "]"
]

emit-value: func [value][
    prin depth 
    probe value
]

=enter-block?=: none

=block=: [
    (
        =enter-block?=: [into =block=] ; we enter blocks by default
        enter-block
    )
    some [
        .here.: block! :.here. ; only enter blocks (R3/R2 compatible)
        (if 1 = length? .value.: first .here. [ =enter-block?=: [skip]  emit-value first .value. ])
        =enter-block?=
        | set .value. skip ( emit-value .value. )
    ]
    (quit-block)
]

STRING-HANDLER: func [data][
    if string? data [
        data: load data
    ]

    parse data =block=
]

STRING-HANDLER A
STRING-HANDLER B
STRING-HANDLER C
STRING-HANDLER D

ask "press enter to quit ..."
于 2014-02-08T15:12:16.967 回答