Monday, 5 May 2014

JavaCC Modern Mode - How to resolve unreachable statement exception

Modern Mode

JavaCC 6.1.0 (yes, that again) introduced a modern code generation option. This mode, which is disabled by default, introduced improved code generation at the cost of perfect backward compatibility with the code generated by the classic (and still default) code generation option.

There are several advantages to the modern code generation option:

  • Decoupling IO from the class library classes via the new generated "Provider" interface.
  • Support for GWT code generation.
  • Better exception handling and error messages (no more throwing instances of java.lang.Error).
  • Significantly less warnings (zero warnings is achievable).
  • Ability to share boilerplate code across parsers.

But,there are also some drawbacks:

  • Generated code has slightly different interfaces therefore a small amount of refactoring involved in code that references the generated code (for an existing codebase).
  • Productions can now only have one return point.
** Note that JavaCC's generated code is still very old fashioned in its generated code style (over use of public and static fields, lack of getters setters, etc). The modern mode is simply a name used to distinguish itself from the backwards compatible code generation.

Unreachable Statement

I am referencing the jbibtex project, maintained by Villu Ruusmann.

If you see exception such as the exceptions shown below in your build, then this is a good indicator that you need to consolidate your return statements within a production::

[INFO] -------------------------------------------------------------
[INFO] -------------------------------------------------------------
[ERROR] d:\jbibtex-master\target\generated-sources\javacc\org\jbibtex\[514,6] error: unreachable statement
[ERROR] d:\jbibtex-master\target\generated-sources\javacc\org\jbibtex\[520,6] error: unreachable statement
[ERROR] d:\jbibtex-master\target\generated-sources\javacc\org\jbibtex\[548,6] error: unreachable statement
[ERROR] d:\jbibtex-master\target\generated-sources\javacc\org\jbibtex\[555,2] error: missing return statement

First, go to the line number corresponding to the file(s) corresponding to the errors in your build:::

The important point here is that there is a return value before the break, therefore the Java compiler senses that the break is redundant. We can see this is happening within the SimpleValue() production, so lets go into the corresponding .jj file (in this case bibtex.jj) and examine the SimpleValue() production.

As you can see above, there are 4 different places where a value is returned. The "modern" code generation style currently does not support multiple return vectors from the same production therefore to resolve this exception, we have to consolidate our return values. The way to do this is via a return value parameter and a single return statement at the end of a production. This is typically trivial.

Now let's rebuild (this is a Maven build):

The build errors are now gone -- BUILD SUCCESS.

The code in this example will shortly be posted on the github page for the jbibtext project. I don't currently classify this as a bug, more as a trade-off, but I will be looking at how to re-enable multiple return vectors in a later release (the classic code generation option, enabled by default still supports multiple return vectors - but at a cost of complexity and warnings).