JavaCC генерирует мертвый код

Я использую JavaCC впервые и замечаю, что он генерирует много мертвого кода. Есть много строк, которые выглядят так (извините за пробел, это автоматически):

{if ("" != null) return result;}
    throw new Error("Missing return statement in function");
  }

Можно ли избежать генерации этого мертвого кода? Это вызывает десятки предупреждений компилятора, которых можно избежать.

Спасибо!

Вот полный минимальный пример из файла .jj:

Statement UseStatement():
{
    String dbName;
}
{
    <USE> dbName=DbObjectName()
    {
        return new UseStatement(dbName);
    }
}

Что генерирует:

final public Statement UseStatement() throws ParseException {String dbName;
    jj_consume_token(USE);
    dbName = DbObjectName();
{if ("" != null) return new UseStatement(dbName);}
    throw new Error("Missing return statement in function");
  }

Кроме того, JavaCC создает файл ParserTokenManager, который выдает ошибку TokenMgrError, но код не компилируется. Он объявляет protected int curChar там, где он должен объявлять char. Поиск в Google этой фразы показывает много примеров, где она правильно объявлена ​​как char - это просто много людей редактируют результат вручную?


person a_physicist    schedule 25.05.2017    source источник
comment
Какую версию JavaCC вы используете? Вы пробовали вариант LEGACY_EXCEPTION_HANDLING = false?   -  person Theodore Norvell    schedule 27.05.2017
comment
Чтобы ответить на ваш вопрос о типе curChar, нет, это не много ручного редактирования. Версия 5 генерирует тип как char.   -  person Theodore Norvell    schedule 27.05.2017
comment
LEGACY_EXCEPTION_HANDLING на самом деле не настраивается пользователем, но его можно изменить — см. мое редактирование ниже. Плагин Maven, который я использовал, использовал версию 6.1.3, но я понял, как вернуться к исходному плагину codehaus и принудительно установить его версию JavaCC на 7.x. Спасибо!   -  person a_physicist    schedule 29.05.2017


Ответы (1)


Я обратился к источнику, и чтобы предотвратить мертвый код, вы должны вызвать Options.isLegacyExceptionHandling.

  // Add if statement to prevent subsequent code generated
  // from being dead code.
  // NB: eclipse now detects 'if (true)' as dead code, so use the more complicated
  // 'if ("" != null)'
  if (inAction  && (Options.isLegacyExceptionHandling()) ) {
    t.image = "{if (\"\" != null) return";
    jumpPatched = true;
  }

который затем запускает:

if (p.isJumpPatched() && !voidReturn) {
  if (isJavaDialect) {
    // TODO :: I don't think we need to throw an Error/Exception to mark that a return statement is missing as the compiler will flag this error automatically
    if (Options.isLegacyExceptionHandling()) {
        codeGenerator.genCodeLine("    throw new "+(Options.isLegacyExceptionHandling() ? "Error" : "RuntimeException")+"(\"Missing return statement in function\");");
    }
  } else {
    codeGenerator.genCodeLine("    throw \"Missing return statement in function\";");
  }
}

https://github.com/javacc/javacc/blob/e38cbdb1db7ca8bd66f892859fef88b4876e69ba/src/main/javacc/JavaCC.jj#L2771-L2779

https://github.com/javacc/javacc/blob/2ac628df1f899fdf6acf1f87fad313b6797085f7/src/main/java/org/javacc/parser/ParseEngine.java#L707-L712

Устаревшая обработка исключений — это производная опция, которая имеет значение false только в том случае, если JAVA_TEMPLATE_TYPE=modern. Единственный способ установить его правильно — включить его в блок options в файле .jj следующим образом:

options {
    JAVA_TEMPLATE_TYPE="modern";
}

Теоретически его также можно установить с помощью параметров командной строки, но на момент написания этой статьи фактически невозможно установить производный параметр до анализа аргументов командной строки (#25)

person a_physicist    schedule 26.05.2017
comment
Есть ли способ отключить «устаревшую обработку исключений»? - person user207421; 27.05.2017
comment
Да - смотрите мои правки. Это немного безумно, но в конце концов я понял. - person a_physicist; 29.05.2017