关于Rebol / Red中自修改解析规则的规则是什么?

时间:2015-04-01 19:48:08

标签: parsing rebol red

我正在研究自我修改规则,并想知道语义究竟是什么以及它们将如何工作。这是一个非常广泛的问题,但我将使用一个特定的“我将如何做到这一点”将其变成一个更集中的问题。 (^(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

我有点困惑它不会崩溃。但假设它以某种方式被防弹,是否有办法让第一个例子起作用?

3 个答案:

答案 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

您基本上使用垃圾内存中的值。