added support for jdk 1.4 assert statements

grammar changes inspired by John Pybus on the antlr-interest mailing list,
see http://groups.yahoo.com/group/antlr-interest/message/4968

the changes to Checker.java are not very clean, but I don't see a better
solution unless the ANTLR api is improved (compilationUnit() should be an
abstract member of Parser, error reporting should be pluggable)
This commit is contained in:
Lars Kühne 2002-03-14 06:19:09 +00:00
parent 4a859be12a
commit e2ec464f27
5 changed files with 244 additions and 14 deletions

View File

@ -73,8 +73,8 @@
<!-- Checks whether the grammar file is newer that the generated code -->
<target name="check.antlr">
<uptodate property="uptodate.antlr"
targetfile="${checkstyle.dir}/GeneratedJavaLexer.java" >
<srcfiles dir= "${checkstyle.dir}" includes="java.g"/>
targetfile="${checkstyle.dir}/GeneratedJava14Lexer.java" >
<srcfiles dir= "${checkstyle.dir}" includes="java.g,java14.g"/>
</uptodate>
</target>
@ -88,6 +88,14 @@
dir="${checkstyle.dir}">
<arg value="java.g" />
</java>
<java classname="antlr.Tool"
classpath="${antlr-tools.jar}"
fork="yes"
dir="${checkstyle.dir}">
<arg value="-glib" />
<arg value="java.g" />
<arg value="java14.g" />
</java>
</target>
<!-- -->
@ -105,12 +113,16 @@
todir="classes/checkstyle"/>
</target>
<!-- Compiles only the test code. Input files are excluded from
compilation, they contain code like assert statements
that does not compile on all JDKs -->
<target name="compile.tests" depends="compile.checkstyle">
<mkdir dir="classes/tests" />
<depend srcdir="src/tests" destdir="classes/tests" closure="yes"/>
<javac srcdir="src/tests"
destdir="classes/tests"
deprecation="on" debug="on"
excludes="**/*nput*.java"
classpathref="tests.buildpath" />
</target>

View File

@ -40,6 +40,95 @@ import org.apache.regexp.RESyntaxException;
public class Checker
implements Defn
{
/**
* Overrides ANTLR error reporting so we completely control
* checkstyle's output during parsing. This is important because
* we try parsing with several grammers (with/without support for
* <code>assert</code>). We must not write any error messages when
* parsing fails because with the next grammar it might succeed
* and the user will be confused.
*/
private class SilentJava14Recognizer extends GeneratedJava14Recognizer
{
/**
* Creates a new <code>SilentJava14Recognizer</code> instance.
*
* @param aLexer the tokenstream the recognizer operates on.
*/
private SilentJava14Recognizer(GeneratedJava14Lexer aLexer)
{
super(aLexer);
}
/**
* Parser error-reporting function, does nothing.
* @param aRex the exception to be reported
*/
public void reportError(RecognitionException aRex)
{
}
/**
* Parser error-reporting function, does nothing.
* @param aMsg the error message
*/
public void reportError(String aMsg)
{
}
/**
* Parser warning-reporting function, does nothing.
* @param aMsg the error message
*/
public void reportWarning(String aMsg)
{
}
}
/**
* Overrides ANTLR error reporting so we completely control
* checkstyle's output during parsing.
*
* @see SilentJava14Recognizer
*/
private class SilentJavaRecognizer extends GeneratedJavaRecognizer
{
/**
* Creates a new <code>SilentJavaRecognizer</code> instance.
*
* @param aLexer the tokenstream the recognizer operates on.
*/
private SilentJavaRecognizer(GeneratedJavaLexer aLexer)
{
super(aLexer);
}
/**
* Parser error-reporting function, does nothing.
* @param aRex the exception to be reported
*/
public void reportError(RecognitionException aRex)
{
}
/**
* Parser error-reporting function, does nothing.
* @param aMsg the error message
*/
public void reportError(String aMsg)
{
}
/**
* Parser warning-reporting function, does nothing.
* @param aMsg the error message
*/
public void reportWarning(String aMsg)
{
}
}
/** configuration */
private final Configuration mConfig;
@ -140,15 +229,38 @@ public class Checker
try {
fireFileStarted(aFileName);
final String[] lines = getLines(aFileName);
VerifierSingleton.getInstance().clearMessages();
VerifierSingleton.getInstance().setLines(lines);
final Reader sar = new StringArrayReader(lines);
final GeneratedJavaLexer jl = new GeneratedJavaLexer(sar);
jl.setFilename(aFileName);
final GeneratedJavaRecognizer jr = new GeneratedJavaRecognizer(jl);
jr.setFilename(aFileName);
jr.setASTNodeClass(MyCommonAST.class.getName());
jr.compilationUnit();
try {
VerifierSingleton.getInstance().clearMessages();
VerifierSingleton.getInstance().setLines(lines);
final Reader sar = new StringArrayReader(lines);
final GeneratedJava14Lexer jl = new GeneratedJava14Lexer(sar);
jl.setFilename(aFileName);
final GeneratedJava14Recognizer jr =
new SilentJava14Recognizer(jl);
jr.setFilename(aFileName);
jr.setASTNodeClass(MyCommonAST.class.getName());
jr.compilationUnit();
}
catch (RecognitionException re) {
// Parsing might have failed because the checked
// filecontains "assert" statement. Retry with a
// grammar that treats "assert" as an identifier
// and not as a keyword
// Arghh - the pain - duplicate code!
VerifierSingleton.getInstance().clearMessages();
VerifierSingleton.getInstance().setLines(lines);
final Reader sar = new StringArrayReader(lines);
final GeneratedJavaLexer jl = new GeneratedJavaLexer(sar);
jl.setFilename(aFileName);
final GeneratedJavaRecognizer jr =
new GeneratedJavaRecognizer(jl);
jr.setFilename(aFileName);
jr.setASTNodeClass(MyCommonAST.class.getName());
jr.compilationUnit();
}
errors = VerifierSingleton.getInstance().getMessages();
}
catch (FileNotFoundException fnfe) {

View File

@ -535,7 +535,15 @@ compoundStatement[MyCommonAST[] aCurlies]
;
// This production provides a slot for adding additional statement productions.
// It is used to simplify an inherited grammar that includes assert statements
// (new Java language feature in JDK 1.4)
statement[int[] aType, MyCommonAST[] aCurlies]
: traditionalStatement[aType, aCurlies]
;
// a traditional (JDK < 1.4) java statement, assert keyword is not allowed
traditionalStatement[int[] aType, MyCommonAST[] aCurlies]
{
final MyModifierSet modSet = new MyModifierSet();
final int[] stmtType = new int[1];
@ -676,9 +684,6 @@ statement[int[] aType, MyCommonAST[] aCurlies]
// empty statement
| s:SEMI {#s.setType(EMPTY_STAT);}
// assert statement
// | "assert"^ expression (COLON^ expression)? SEMI!
;

View File

@ -0,0 +1,80 @@
////////////////////////////////////////////////////////////////////////////////
// checkstyle: Checks Java source code for adherence to a set of rules.
// Copyright (C) 2001-2002 Oliver Burn
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
////////////////////////////////////////////////////////////////////////////////
header {
package com.puppycrawl.tools.checkstyle;
}
/** Java 1.4 Recognizer
*
* Based heavily on the Grammer example that comes with ANTLR. See
* http://www.antlr.org.
*
*/
class GeneratedJava14Recognizer extends GeneratedJavaRecognizer;
// Options don't get inherited, copy of option block required.
options {
k = 2; // two token lookahead
exportVocab=GeneratedJava14; // Call its vocabulary "GeneratedJava14"
codeGenMakeSwitchThreshold = 2; // Some optimizations
codeGenBitsetTestThreshold = 3;
defaultErrorHandler = false; // Don't generate parser error handlers
buildAST = true;
}
// overrides the statement production in java.g, adds assertStatement
statement[int[] aType, MyCommonAST[] aCurlies]
: traditionalStatement[aType, aCurlies]
| assertStatement[aType, aCurlies]
;
// assert statement, available since JDK 1.4
assertStatement[int[] aType, MyCommonAST[] aCurlies]
{
final MyModifierSet modSet = new MyModifierSet();
final int[] stmtType = new int[1];
final MyCommonAST[] stmtBraces = new MyCommonAST[2];
stmtType[0] = STMT_OTHER;
}
: ASSERT^ expression ( COLON! expression )? SEMI!
;
class GeneratedJava14Lexer extends GeneratedJavaLexer;
options {
exportVocab=GeneratedJava14; // call the vocabulary "GeneratedJava14"
testLiterals=false; // don't automatically test for literals
k=4; // four characters of lookahead
charVocabulary='\u0003'..'\uFFFF';
codeGenBitsetTestThreshold=20;
}
tokens {
ASSERT="assert";
}
// antlr expects a definition here: 'unexpected token: null'
// To avoid that message, one definition from GeneratedJavaLexer
// is repeated. Rather inelegant but I didn't find a better solution :-(
// Feel free to improve this...
protected
FLOAT_SUFFIX
: 'f'|'F'|'d'|'D'
;

View File

@ -136,4 +136,25 @@ class InputWhitespace
o . toString();
return o.toString();
}
/** assert statement test */
public void assertTest()
{
// OK
assert true;
// OK
assert true : "Whups";
// evil colons, should be OK
assert "OK".equals(null) ? false : true : "Whups";
// WS tests for assert not implemented yet
// missing WS around assert
// assert(true);
// missing WS around colon
// assert true:"Whups";
}
}