红色的递归解析
Recursive parse in Red
我想从输入中解析跳过 Forth 风格的 if,Forth 风格意味着每个 if 以 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
所以其中三个失败了,因为它们包含介于一个 then
和另一个之间的东西(5
在这种情况下)。
修复可能非常简单明了,但我现在看不到。如果可能的话,你能帮我修正上面的规则,或者展示一个通过所有测试的不同的规则吗?
我不确定您的规则是否可修复,因为它严重依赖递归,但未能提供测试 #5 所需的迭代支持。我无法修复它,因为 skip
用于消耗终端和 non-terminal 令牌(包括 if
),所以这让我很难理解。
我想出了一个不同的解决方案。它更长,但通过了所有测试(使用红色):
rules: [
'if skip
opt ['else [some rules | skip]]
opt some rules
'then
opt [some rules | ahead 'then | skip]
]
备注:
- 我尽量使语法规则明确。
- 请注意
some
的用法以迭代方式使用 sub-expressions。
-
ahead 'then
保护规则是为了防止 skip
消耗额外的 then
,这将是父表达式的一部分(在递归调用的情况下)。
- 它使用
skip
传递then
或else
之后的终端值,但从您的描述中不清楚那里是否可以有多个值。无论如何,如果需要,很容易扩展以匹配更复杂的模式。
如果你想使用这样的规则来跳过输入,你可以这样调用它:
skip-ifs: [to 'if rules]
希望这对您有所帮助。
我想从输入中解析跳过 Forth 风格的 if,Forth 风格意味着每个 if 以 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
所以其中三个失败了,因为它们包含介于一个 then
和另一个之间的东西(5
在这种情况下)。
修复可能非常简单明了,但我现在看不到。如果可能的话,你能帮我修正上面的规则,或者展示一个通过所有测试的不同的规则吗?
我不确定您的规则是否可修复,因为它严重依赖递归,但未能提供测试 #5 所需的迭代支持。我无法修复它,因为 skip
用于消耗终端和 non-terminal 令牌(包括 if
),所以这让我很难理解。
我想出了一个不同的解决方案。它更长,但通过了所有测试(使用红色):
rules: [
'if skip
opt ['else [some rules | skip]]
opt some rules
'then
opt [some rules | ahead 'then | skip]
]
备注:
- 我尽量使语法规则明确。
- 请注意
some
的用法以迭代方式使用 sub-expressions。 -
ahead 'then
保护规则是为了防止skip
消耗额外的then
,这将是父表达式的一部分(在递归调用的情况下)。 - 它使用
skip
传递then
或else
之后的终端值,但从您的描述中不清楚那里是否可以有多个值。无论如何,如果需要,很容易扩展以匹配更复杂的模式。
如果你想使用这样的规则来跳过输入,你可以这样调用它:
skip-ifs: [to 'if rules]
希望这对您有所帮助。