如果第二条规则失败,请尝试第一条规则 [英] Try the first rule if the second rule fails

查看:67
本文介绍了如果第二条规则失败,请尝试第一条规则的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我定义了两组标识符 IDENTIFIER_ONEIDENTIFIER_TWO,它们都是 IDENTIFIER 的专有子集.我想编写一个解析器:

I have defined two sets of identifiers IDENTIFIER_ONE and IDENTIFIER_TWO which are both exculsive subsets of IDENTIFIER. I would like to write a parser such that:

"i1(arg) EOS" can't be parsed (1)
"i2(arg) EOS" can be parsed (2)
"i1(arg) = value EOS" can be parsed (3)
"i2(arg) = value EOS" can be parsed (4)

其中 i1(resp., i2) 属于 IDENTIFIER_ONE (resp., IDENTIFIER_TWO);argvalue 属于 IDENTIFIER.下面的parser.mly已经实现了我所追求的所有点,除了(4):

where i1(resp., i2) belongs to IDENTIFIER_ONE (resp., IDENTIFIER_TWO); arg and value belong to IDENTIFIER. The following parser.mly has already realized all the points I am after, except (4):

identifier:
| IDENTIFIER_ONE { $1 }
| IDENTIFIER_TWO { $1 } 

block_statement_EOS:
| identifier LPAREN identifier RPAREN EQUAL identifier EOS { BSE_Let ($1, $3, $6) }
| IDENTIFIER_TWO LPAREN identifier RPAREN EOS { BSE_I_I ($1, $3) }

给定 i1(arg) = value EOS 作为输入,作为目标 (3) 它被正确读取为 BSE_Let (i1, arg, value).然而,给定i2(arg) = value EOS 作为输入,它在读取EQUAL 后停止解析.我猜是因为一旦解析遇到i2(arg),就去到block_statement_EOS的第二条规则,后面的EQUAL就不行了被解析.

Given i1(arg) = value EOS as input, as goal (3) it is correctly read as BSE_Let (i1, arg, value). However, given i2(arg) = value EOS as input, it stops the parsing after reading EQUAL. I guess it is because once the parse meets i2(arg), it goes to the 2nd rule of block_statement_EOS, and later EQUAL can't be parsed.

理想情况下,如果第二条规则失败,我希望解析器可以尝试 block_statement_EOS 的第一条规则.有人能帮我实现这个吗?

Ideally, I would hope the parser could try the 1st rule of block_statement_EOS if the 2nd rule fails. Could anyone help me to make this possible?

PS:如果我把parser.mly写成如下,所有的目标都可以实现.有谁知道为什么?此外,我真的不喜欢这种解决方法,因为我确实需要编写 identifier 而不是许多其他规则中的两个子集,我希望有一个更优雅的解决方案...

PS: If I write the parser.mly as follows, all the goals can be achieved. Does anyone know why? Additionally I really don't like this workaround, because I do need to write identifier instead of two subsets in many other rules, I would hope a more elegant solution...

block_statement_EOS:
| IDENTIFIER_ONE LPAREN identifier RPAREN EQUAL identifier EOS { BSE_Let ($1, $3, $6) }
| IDENTIFIER_TWO LPAREN identifier RPAREN EQUAL identifier EOS { BSE_Let ($1, $3, $6) }
| IDENTIFIER_TWO LPAREN identifier RPAREN EOS { BSE_I_I ($1, $3) }

推荐答案

当你的解析器遇到 IDENTIFIER_TWO 之后的 LPAREN 时,它必须决定是移还是移减少:

When your parser encounters an LPAREN after an IDENTIFIER_TWO, it has to decide whether to shift or to reduce:

  • shift:将LPAREN 放入栈中;
  • reduce:用identifier替换栈顶的IDENTIFIER_TWO.
  • shift: put LPAREN on the stack;
  • reduce: replace IDENTIFIER_TWO, which is on top of the stack, by identifier.

如果你的解析器选择移动,它永远不会将这个特定的 IDENTIFIER_TWO 减少到 identifier(因为这个特定的 IDENTIFIER_TWO 永远不会在上面堆栈再次),这意味着它总是会减少block_statement_EOS的第二条规则.

If your parser chooses to shift, it will never reduce this particular IDENTIFIER_TWO into identifier (because this particular IDENTIFIER_TWO will never be on top of the stack again), meaning that it will always reduce the second rule of block_statement_EOS.

如果您的解析器选择减少,它永远不会减少 block_statement_EOS 的第二条规则,因为该规则以 IDENTIFIER_TWO 而不是 identifier 开头.

If your parser chooses to reduce, it will never reduce the second rule of block_statement_EOS, as this rule starts with IDENTIFIER_TWO and not identifier.

这就是您的第二个版本有效的原因,因为在 IDENTIFIER_TWO 之后无需在移位和减少之间进行选择.如果您愿意,可以稍后进行选择.

This is why your second version works, because there is no need to choose between shifting and reducing after IDENTIFIER_TWO. The choice is made later, if you wish.

这篇关于如果第二条规则失败,请尝试第一条规则的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆