我已经定义了两组标识符IDENTIFIER_ONE
,IDENTIFIER_TWO
它们都是IDENTIFIER
. 我想写一个解析器,这样:
"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
); arg
并且value
属于IDENTIFIER
。以下parser.mly
已经实现了我所追求的所有要点,除了(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
就无法解析了。
block_statement_EOS
理想情况下,如果第二条规则失败,我希望解析器可以尝试第一条规则。谁能帮助我使这成为可能?
PS:如果我写parser.mly
如下,所有的目标都可以实现。有谁知道为什么?另外我真的不喜欢这种解决方法,因为我确实需要identifier
在许多其他规则中编写而不是两个子集,我希望有一个更优雅的解决方案......
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) }