Red中的递归解析

时间:2017-02-11 14:36:23

标签: parsing rebol red

我想解析 - 跳过Forth-style if来自输入,Forth-style意味着每个以if开头并以then结尾,假设所有输入都是正确的,不需要处理不匹配。

问题是if的每个部分都可以递归地包含任意数量的其他if

以下是我使用测试用例的最佳解决方案:

Red []

skip-nested-ifs: [skip to ['if | 'then] skip-nested-ifs-helper]
skip-nested-ifs-helper: ['then | skip-nested-ifs skip-nested-ifs-helper ]


rules: skip-nested-ifs

test-cases: [
   [if a then]
   [if a else b then]
   [if a if b then then]
   [if a if b then 5 then]
   [if a if b then 5 if c then then]
   [if a else if b then then]
   [if a else if b then 5 then]
   [if a else if b then if c then then]
   [if a if b if c then if d then then then]
]

forall test-cases [
   prin [mold test-cases/1 ""]
   print either parse test-cases/1 rules [ "OK" ] [ "FAIL" ]
]

输出结果为:

[if a then] OK
[if a else b then] OK
[if a if b then then] OK
[if a if b then 5 then] FAIL
[if a if b then 5 if c then then] FAIL
[if a else if b then then] OK
[if a else if b then 5 then] FAIL
[if a else if b then if c then then] OK
[if a if b if c then if d then then then] OK

因此,其中三个失败,因为它们在一个5和另一个then之间包含某些内容(在这种情况下为Cannot set the value of read-only property 'xxx')。

可能修复非常简单明了,但我现在还没看到。如果可能的话,你能帮我解决上面的规则吗?或者显示一个通过所有测试的不同规则?

1 个答案:

答案 0 :(得分:5)

我不确定您的规则是否可修复,因为它严重依赖递归,但无法提供测试#5所需的迭代支持。我无法修复它,因为std::vector<int> v = {2, 3, 3}; v = std::move(v); // undefined behavior 用于使用终端和非终端令牌(包括skip),因此我很难跟进。

我想出了一个不同的解决方案。它更长,但通过所有测试(使用红色):

if

注意:

  • 我尽量使语法规则尽可能明确。
  • 注意使用rules: [ 'if skip opt ['else [some rules | skip]] opt some rules 'then opt [some rules | ahead 'then | skip] ] 迭代使用子表达式。
  • some防护规则,是为了防止ahead 'then消耗额外的skip,这将是父表达式的一部分(在递归调用的情况下)。
  • 它使用then来传递skipthen之后的终端值,但是从您的描述中不清楚那里是否有多个值。无论如何,如果需要,可以很容易地扩展以匹配更复杂的模式。

如果你想使用这样的规则来跳过输入,你可以这样调用它:

else

希望这有帮助。