【问题标题】:What are the rules about self-modifying parse rules in Rebol/Red?Rebol/Red 中关于自修改解析规则的规则是什么?
【发布时间】:2015-04-01 19:48:07
【问题描述】:

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

我有点困惑它是如何不崩溃的。但是假设它以某种方式被防弹,有没有办法让第一个例子工作?

【问题讨论】:

  • 跳过插入的字符怎么样?规则:[“a”“b”(插入查找规则“d”“c”探测规则)跳过“d”“e”];返回true

标签: parsing rebol red


【解决方案1】:

这行得通

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

【讨论】:

    【解决方案2】:

    这可能有效:

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

    【讨论】:

      【解决方案3】:

      但假设它以某种方式防弹......

      在 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
      

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

      【讨论】:

      • 如果 Rebol 中的语法是“自修改的”,那么它本质上是一个 adaptive grammar
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-01-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-12-26
      • 2011-05-06
      相关资源
      最近更新 更多