java - 如何消除 JavaCC 中的选择冲突?
问题描述
我的生产规则如下:
OtherNonTerminal := NonTerminal | {}
NonTerminal := <TOKEN>:A() | <TOKEN>:A(), Nonterminal()
在 JavaCC 中,NonTerminal 存在选择冲突:
void OtherNonTerminal() : {}
{
Nonterminal() | {}
}
void Nonterminal() : {}
{
<TOKEN> <COLON> A()
|
<TOKEN> <COLON> A() <COMMA> Nonterminal()
}
这会是摆脱选择冲突的一种方法吗?程序是否会像我的 NonTerminal 生产规则一样按规定工作?
void Nonterminal() : {}
{
<TOKEN> <COLON> A() (<COMMA> NonTerminal())?
}
解决方案
为什么会出现问题
在 JavaCC 中,决定采用哪个分支的默认方法是查看下一个标记。如果令牌与第一选择兼容,则采取第一选择并且该决定是不可逆的。没有回溯。
所以看选择
void Nonterminal() : {}
{
<TOKEN> <COLON> A()
|
<TOKEN> <COLON> A() <COMMA> Nonterminal()
}
并假设输入中的下一个标记是<TOKEN>
。无论是否有<COMMA>
后一个,都会采取第一个选择。换句话说
<TOKEN> <COLON> A()
| <TOKEN> <COLON> A() <COMMA> Nonterminal()
相当于
<TOKEN> <COLON> A()
除了第一个会产生一条警告消息,因为 JavaCC 认为您编写的内容没有意义。
一个很好的解决方案
您的问题的答案是“是”。一种解决方案是做你所做的并分解出公共前缀
void Nonterminal() : {}
{
<TOKEN> <COLON> A() (<COMMA> NonTerminal())?
}
可能更好的解决方案,具体取决于
如果由于某种原因,您真的不知道要考虑什么,您还可以执行以下操作
void Nonterminal() : {}
{
LOOKAHEAD( <TOKEN> <COLON> A() <COMMA>)
<TOKEN> <COLON> A() <COMMA> Nonterminal()
|
<TOKEN> <COLON> A()
}
在这里,解析器将在输入流中向前看。如果它看到逗号,则采取第一个选择。否则,第二个。
如果两种情况下的语义动作不同,这可能很有用。例如
LOOKAHEAD( <TOKEN> <COLON> A() <COMMA>)
<TOKEN> {doSomething();} <COLON> A() <COMMA> Nonterminal()
|
<TOKEN> {doSomethingDifferent();} <COLON> A()
非递归解决方案。
第三种选择是
void Nonterminal() : {}
{
Foo() (<COMMA> Foo() )*
}
void Foo() : {}
{
<TOKEN> <COLON> A()
}
推荐阅读
- c# - 一旦我将脚本应用到场景编辑器中的游戏对象,我的函数就会运行。我需要它只在运行时影响对象
- python - 将 .isin 应用于熊猫中每一行的有效方法
- spring-boot - @Autowire 如何在 spring-boot 单元测试中工作?
- ansible - 用于安装 mod_ssl、python-passlib 和 firewalld 的 Ansible-Playbook(并始终保持最新)
- python - 如何通过在中间插入/更改字符来修改文本文件?
- css - CSS Grid:`grid-auto-flow: row` 无法水平对齐子项
- html - 图像在 Chrome 但不是 Firefox 中加载
- algorithm - 索引 N 维向量
- maven - 改成kafka_2.11后包kafka.producer不存在
- java - CardView 没有使用 LayoutInflater 正确充气