Необычно используется синтаксис Java (JavaParser)?

Я изучаю парсер грамматики Java и наткнулся на этот странный кусок кода, который я обычно не использую в обычном коде. Взято из https://code.google.com/p/javaparser/source/browse/branches/mavenized/JavaParser/src/main/java/japa/parser/ASTParser.java#1998

У него есть много функций, содержащих код, например

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, и он делает свою работу! Я сбит с толку. Как несколько строк выдают исключение после возврата?

9 голосов | спросил Nederealm 28 Mayam14 2014, 11:52:54

1 ответ


0

Это действительно правильный код, не видя всего, я вижу некоторые странности:

  • «Неверное» имя переменной и метода, иногда с использованием PascalCase.
  • Переменная экземпляра token
  • Статическая переменная IDENTIFIER

Тогда:

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);
}

Это бесконечный цикл, который продолжается до тех пор, пока jj_2_17(2) возвращает true, но появляется , чтобы ничего не делать с этим результатом. Он разрывает из label_23, когда выражение было false. Чтобы еще больше сбить с толку будущих читателей, он фактически делает , только если выражение true false), а именно последние три строки.

Для получения дополнительной информации label_23 - это просто метка, которую можно использовать только в while и for. Затем вы можете вырвать из этого цикла при использовании break labelName;.

Пример, который выходит из внешнего цикла из внутреннего цикла:

outerLoop: for (int i = 0; i < max; i++) {
    innerLoop: for (int j = 0; j < max2 - i; j++) {
        if (something) {
            break outerLoop;
        }
        //...
    }
}

Вы также можете использовать continue в сочетании с метками.

Затем мы видим блок без границ, который всегда возвращает ret:

{
    if (true) {
        return ret;
    }
}

Так что все в порядке. Я думаю, что мы также можем с большой вероятностью заключить, что этот код был машинно-генерируемым.

ответил skiwi 28 Maypm14 2014, 12:02:01

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132