不常用的Java语法(JavaParser)?
我正在探索一个Java语法分析器,我遇到了一段普通代码中通常不会用到的奇怪代码。取自 它有许多包含代码的函数,例如不常用的Java语法(JavaParser)?,java,algorithm,syntax,syntax-error,Java,Algorithm,Syntax,Syntax Error,我正在探索一个Java语法分析器,我遇到了一段普通代码中通常不会用到的奇怪代码。取自 它有许多包含代码的函数,例如 final public NameExpr Name() throws ParseException { NameExpr ret; jj_consume_token(IDENTIFIER); ret = new NameExpr(token.beginLine, token.beginColumn, token.endLine, token.endCol
final public NameExpr Name() throws ParseException {
NameExpr ret;
jj_consume_token(IDENTIFIER);
ret = new NameExpr(token.beginLine, token.beginColumn, token.endLine, token.endColumn, token.image);
label_23: while (true) {
if (jj_2_17(2)) {
;
} else {
break label_23;
}
jj_consume_token(DOT);
jj_consume_token(IDENTIFIER);
ret = new QualifiedNameExpr(ret.getBeginLine(), ret.getBeginColumn(), token.endLine, token.endColumn, ret, token.image);
}
{
if (true) {
return ret;
}
}
throw new Error("Missing return statement in function");
}
乍一看,它似乎很奇怪,但毫无疑问,它是有效的,因为我可以编译它。但是有人能解释一下它是如何工作的吗?我试着输入无效的Java语法,它做到了!我很困惑。返回后,几行如何抛出异常?这确实是有效的代码,在没有看到所有内容的情况下,我可以看到一些奇怪之处:
- “不正确”变量和方法命名,有时使用PascalCase
- 实例变量
token
- 静态变量
标识符
jj_2_17(2)
返回true
,它就会一直运行,但在该结果出现时不会执行任何操作。当表达式为false
时,它从标签23
中断开。让未来的读者更加困惑的是,只有当表达式是true
(当它在false
上断开时)即最后三行时,它才真正起作用
关于进一步的信息,标签\u 23
只是一个标签,只能在上使用,而和用于
循环。然后,当使用break labelName时,您可以将从该循环中断开代码>
从内环中断开外环的示例:
outerLoop: for (int i = 0; i < max; i++) {
innerLoop: for (int j = 0; j < max2 - i; j++) {
if (something) {
break outerLoop;
}
//...
}
}
所以这一切都是有效的。我想我们也很有可能得出结论,这段代码是机器生成的。这里可能最让人困惑的是if-else在while中阻塞了
事实上,如果:
if(!jj_2_17(2)) {
break label_23;
}
jj_consume_token(DOT);
jj_consume_token(IDENTIFIER);
ret = new QualifiedNameExpr(ret.getBeginLine(), ret.getBeginColumn(), token.endLine, token.endColumn, ret, token.image);
所以实际上这段代码只返回最后一个QualifiedNameExpr(/*…*/)可以解析的代码>
关于你在评论中提到的“无法到达的投掷”。想象一下,当您创建一个方法(在eclipse或netbeans中)而不添加return语句时会发生什么
生成的代码(假设这里是生成的代码)不包含return语句,然后突然抛出错误。这导致eclipse/netbeans/[insert IDE here]告诉您“函数中缺少返回语句”,这正是该语句的目的……确保识别不理解的确切代码/语法:即它是“标签”吗?“空话”?“无用的抛出”?我无法给出答案,因为我从来没有遇到过这样的事情,但这似乎在Oracle教程中有概述。是的,我指的是块标签、围绕返回的额外大括号、无用的if语句和不可到达的抛出。它看起来像是生成的代码。也许从Antral?break到label是goto的邪恶表亲。这个类似乎是根据其大小手动完成的,并且必须手动对所有标签进行编码?@Nederealm我想说这个代码强烈表明它是机器生成的。为了回答您关于标签只能用于while或for循环的观点,从技术上讲,不仅如此。break语句对于没有循环的标记块也是有效的。请参阅我的编辑。
{
if (true) {
return ret;
}
}
if (jj_2_17(2)) {
;
} else {
break label_23;
}
jj_consume_token(DOT);
jj_consume_token(IDENTIFIER);
ret = new QualifiedNameExpr(ret.getBeginLine(), ret.getBeginColumn(), token.endLine, token.endColumn, ret, token.image);
if(!jj_2_17(2)) {
break label_23;
}
jj_consume_token(DOT);
jj_consume_token(IDENTIFIER);
ret = new QualifiedNameExpr(ret.getBeginLine(), ret.getBeginColumn(), token.endLine, token.endColumn, ret, token.image);