2

我想从输入中解析跳过 Forth 风格的 if,Forth 风格意味着每个 if 都以 开头if和结尾then,假设所有输入都是正确的,不需要处理不匹配。

问题是每个部分都if可以递归地包含任意数量的 other 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

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

4

1 回答 1

5

我不确定您的规则是否可修复,因为它严重依赖递归,但无法提供测试#5 所需的迭代支持。我无法修复它,因为skip它用于消耗终端和非终端令牌(包括if),所以这让我很难理解。

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

rules: [
    'if skip 
    opt ['else [some rules | skip]]
    opt some rules
    'then
    opt [some rules | ahead 'then | skip]
]

笔记:

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

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

skip-ifs: [to 'if rules]

希望这可以帮助。

于 2017-02-12T14:48:19.283 回答