我正在研究自我修改规则,并想知道语义究竟是什么以及它们将如何工作。这是一个非常广泛的问题,但我将使用一个特定的“我将如何做到这一点”将其变成一个更集中的问题。 (^(64)是小写“d”的十六进制ascii,因此无法找到它)
rule: ["a" "b" (insert find rule "^(64)" "c" probe rule) "d" "e"]
parse "abcde" rule
如果我跑了,我得到(Rebol和Red):
["a" "b" (insert find rule "d" "c" probe rule) "c" "d" "e"]
== false
规则似乎已经更新,并且以相当“安全的方式”更新(如果有任何安全的话)。还有更多邪恶的版本:
rule: ["a" "b" (clear rule probe rule) "d" "e"]
parse "abcde" rule
Rebol和Red都得到了:
[]
== false
我有点困惑它不会崩溃。但假设它以某种方式被防弹,是否有办法让第一个例子起作用?
答案 0 :(得分:2)
这有效
>> rule: ["a" "b" (insert first find rule block! "c" probe rule ) [] "d" "e"]
== ["a" "b" (insert first find rule block! "c" probe rule) [] "d" "e"]
>> parse "abcde" rule
["a" "b" (insert first find rule block! "c" probe rule) ["c"] "d" "e"]
== true
因为规则元素的数量和第一级规则游标的位置没有改变。第二级似乎在入场时被加载。
这也有效
>> rule: ["a" "b" (insert first find rule "d" "c" probe rule ) "d" "e"]
== ["a" "b" (insert first find rule "d" "c" probe rule) "d" "e"]
>> parse "abcde" rule
["a" "b" (insert first find rule "d" "c" probe rule) "cd" "e"]
== true
在自我修改规则的一般形式中,您可以使用可以更改或替换的变体下级规则
sub_rule: []
rule: ["a" "b" (sub_rule: "c" probe rule) sub_rule "d" "e"]
parse "abcde" rule
["a" "b" (sub_rule: "c" probe rule) sub_rule "d" "e"]
== true
答案 1 :(得分:1)
这可能有效:
>> rule: ["a" "b" m: (insert find rule "^(64)" "c" probe rule) skip "d" "e"]
或
>> rule: ["a" "b" m: (insert find rule "^(64)" "c" probe rule m: next m) :m "d" "e"]
>> parse "abcde" rule
["a" "b" m: (insert find rule "d" "c" probe rule m: next m) :m "c" "d" "e"]
== true
答案 2 :(得分:0)
但假设它以某种方式被防弹......
在R3-Alpha中它没有,如果你运气不好(例如通过引发一系列扩展),你可以通过这样做来崩溃。见#2214: "Modifying running PARSE rule leads to execution beyond rule TAIL, possible crash"
所以你应该不修改PARSE当前正在处理的规则。但是,如果该规则未在该时刻运行,您可以 - 修改规则内的嵌套规则:
subrule: ["c"]
rule: ["a" (insert subrule "b") subrule]
parse "abc" rule
这是在Ren-C build中通过在解析器遍历它们时修改锁定规则来形式化的。解析器的另一种方法是测试规则中每次提取的长度,如果超过长度则中止。虽然这可以防止崩溃,但这会导致复杂和狡猾的行为 - 并通过支付支票来降低性能。
(由于类似的原因,在Ren-C中,您无法修改当前正在使用DO执行的块。但是通过修改不运行的嵌套括号组,您可以完成与PARSE相同的解决方法的上方。)
rule: ["a" "b" (clear rule probe rule) "d" "e"] parse "abcde" rule
我有点困惑它不会崩溃。
在Rebol的R3-Alpha中,这个特殊情况不会崩溃或抱怨,因为它不会回收系列中的内存,除非它扩展并需要新的分配。它只是在系列的头部位置写一个终结符(覆盖" a")并调整缓存长度。 PARSE忽略长度,只查找END标记。所以它一直走,直到找到陈旧的旧标记。
要看到这一点,你也可以尝试:
>> rule: ["a" "b" (clear rule) "c" "d" "e"]
== ["a" "b" (clear rule) "c" "d" "e"]
>> parse "abcde" rule
== true
您基本上使用垃圾内存中的值。