我遇到了需要等同的情况,例如:
[
{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的引擎,它可以为{Foo}
,[{Foo}]
和[{Foo} /some-refinement]
运行相同的处理程序(让我们称之为STRING-HANDLER),并且仅使用正确数量的参数调用它。
在没有PARSE的情况下写这个很容易......一个元素被包装在一个临时块中(如果它不是一个块)。然后在CASE语句中测试第一个项目。但是我想将它转换为基于PARSE的,其中一个分支使用INTO而另一个分支不使用,而不重复代码。
它需要支持嵌套,因此您最终可能会处理以下内容:
[http://example.com/some/stuff.html [{Foo} /some-refinement] 3]
答案 0 :(得分:1)
我希望以下内容可以作为您解决方案的基础。
以下内容在R2和R3中的表现完全相同。 PARSE的'投入使用在两者之间非常不同所以我放了一个简单的警卫[.here.: block! :.here.]
来修复两个平台中不同的错误情况。
我使用了钩子函数,它允许干净地将数据浏览与数据评估分开。如果你仔细观察,你会注意到= enter-block?=:rule是全局的,并且在运行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 ..."