2017-02-11 55 views
2

我想解析 - 跳过Forth风格,如果从输入,Forth风格意味着每个如果以if开头并以then结尾,假设所有输入都是正确的,则不需要处理不匹配。红色递归解析

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

这里是一个测试案例我最好的解决办法:一个then之间

[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在这种情况下):

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

输出是另一个。

可能修复很简单明显,但我现在看不到它。如果可能的话,你能帮助我解决上述规则吗?还是显示出通过所有测试的不同规则?

+0

在第一条规则中,你是否使用了'to',或者你真的想'穿过'而不是? – DocKimbel

+0

'parse-trace'对于调试解析很有用 –

+0

@DocKimbel我之后使用'to'来故意匹配'then',因为如果先找到'then' - 这意味着当前'if'完成,否则我们就会嵌套一。 – user3033648

回答

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来传递thenelse之后的终端值,尽管从描述中不清楚是否存在多个值。无论如何,如果需要的话,扩展匹配更复杂的模式很容易。

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

skip-ifs: [to 'if rules] 

希望这有助于。

+0

感谢您的解决方案,但规则中的最后一项:'opt [some rules |提前'然后|如果在当前有一个之后,'也跳过下一个'if',就像这里:'[if a then if then]'。我想只跳过一次,下一次将单独处理。你认为这是可能的吗? – user3033648

+0

只需将'ahead'替换为'ahead''if if | '然后]'它也会正确解析这种不同的模式。 – DocKimbel

+0

我试过'选择[一些规则|提前['if'then] |跳过]'作为规则的最后一部分,它失败了一半的测试 – user3033648