你的假设没有错。你正在尝试做的事情应该工作。它应该工作的原因你认为它应该工作。
这是一个用JavaCC编写的完整示例。
void Start() : {} { Xi() <EOF> }
void Xi() : {} {
LOOKAHEAD(Phi()) Phi() { System.out.println("Phi") ; }
| LOOKAHEAD(Psi()) Psi() { System.out.println("Psi") ; }
}
void Phi() : {} { Phi_sub() (("&&" | "||") Phi_sub())*}
void Phi_sub() : {} { "(" Phi() ")" | "Phi_sub" }
void Psi() : {} { Psi_sub() (("&&" | "||") Psi_sub())* }
void Psi_sub() : {} { "(" Psi() ")" | "Psi_sub" }
这里是一些样本输出:
Input is : <<Phi_sub>>
Phi
Input is : <<Psi_sub>>
Psi
Input is : <<((Phi_sub && Phi_sub) || Phi_sub)>>
Phi
Input is : <<((Psi_sub && Psi_sub) || Psi_sub)>>
Psi
您有谎言在问题未示出的东西的问题。
顺便说一句,在每个备选方案的前面放一个lookahead规范是一个坏主意。
void X() : {} { LOOKAHEAD(Y()) Y() | LOOKAHEAD(Z()) Z() }
大致相当于
void X() : {} { LOOKAHEAD(Y()) Y() | LOOKAHEAD(Z()) Z() | fail with a stupid error message }
例如,这里是上面的语法
Input is : <<((Psi_sub && Psi_sub) || Phi_sub)>>
NOK.
Encountered "" at line 1, column 1.
Was expecting one of:
毕竟前瞻失败的另一个运行,解析器留下一个空集的期望!
如果更改Xi
到
void Xi() : {} {
LOOKAHEAD(Phi()) Phi() { System.out.println("Phi") ; }
| Psi() { System.out.println("Psi") ; }
}
你得到一个稍微好一点的错误信息
Input is : <<((Psi_sub && Psi_sub) || Phi_sub)>>
NOK.
Encountered " "Phi_sub" "Phi_sub "" at line 1, column 26.
Was expecting one of:
"(" ...
"Psi_sub" ...
您还可以自定义错误消息
void Xi() : {} {
LOOKAHEAD(Phi()) Phi() { System.out.println("Phi") ; }
| LOOKAHEAD(Psi()) Psi() { System.out.println("Psi") ; }
| { throw new ParseException("Expected either a Phi or a Psi at line "
+ getToken(1).beginLine
+ ", column " + getToken(1).beginColumn + ".") ;
}
}
谢谢你,所以现在我知道,这个问题很可能是被忽略的内部预测。我将(i)尝试将Phi和Psi加入到单个生产中,然后在语义上检查Phi是Phi还是Psi是Psi,或者(ii)在另一个解析器生成器中重写该语法。 – arataj
语法预测规范在语法预测期间被忽略。请参阅FAQ中的讨论。这是我从来没有理解的理由。如果你发布一个完整的最小失败例子作为一个新问题,有人可能会弄清楚。 –