From 82de45f06f33da885e109e5420a156ab67136156 Mon Sep 17 00:00:00 2001 From: Oliver Burn Date: Mon, 26 Nov 2001 12:25:45 +0000 Subject: [PATCH] Incorporate changes made to the ANTLR Java grammar --- ChangeLog | 5 + .../com/puppycrawl/tools/checkstyle/java.g | 164 +++++++++++------- .../puppycrawl/tools/checkstyle/java.tree.g | 21 ++- 3 files changed, 127 insertions(+), 63 deletions(-) diff --git a/ChangeLog b/ChangeLog index d043b55f1..186f278ab 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,10 @@ 2001-11-26 Oliver Burn + * src/checkstyle/com/puppycrawl/tools/checkstyle/java.g + * src/checkstyle/com/puppycrawl/tools/checkstyle/java.tree.g: + Incorporate changes made to the ANTLR Java grammar that checkstyle is + based off. + * src/tests/com/puppycrawl/tools/checkstyle/CheckerTest.java * src/checkstyle/com/puppycrawl/tools/checkstyle/java.g: Included patch to check whitespace after synchronized and catch keywords. From Lars diff --git a/src/checkstyle/com/puppycrawl/tools/checkstyle/java.g b/src/checkstyle/com/puppycrawl/tools/checkstyle/java.g index 4fbca2ecf..80849b610 100644 --- a/src/checkstyle/com/puppycrawl/tools/checkstyle/java.g +++ b/src/checkstyle/com/puppycrawl/tools/checkstyle/java.g @@ -56,6 +56,7 @@ tokens { POST_INC; POST_DEC; METHOD_CALL; EXPR; ARRAY_INIT; IMPORT; UNARY_MINUS; UNARY_PLUS; CASE_GROUP; ELIST; FOR_INIT; FOR_CONDITION; FOR_ITERATOR; EMPTY_STAT; FINAL="final"; ABSTRACT="abstract"; + STRICTFP="strictfp"; SUPER_CTOR_CALL; CTOR_CALL; } { @@ -112,16 +113,6 @@ declaration! {#declaration = #v;} ; -// A list of zero or more modifiers. We could have used (modifier)* in -// place of a call to modifiers, but I thought it was a good idea to keep -// this rule separate so they can easily be collected in a Vector if -// someone so desires -modifiers - : ( modifier )* - {#modifiers = #([MODIFIERS, "MODIFIERS"], #modifiers);} - ; - - // A type specification is a type name with possible brackets afterwards // (which would make it an array type). typeSpec[boolean addImagNode] @@ -192,6 +183,14 @@ identifierStar } ; +// A list of zero or more modifiers. We could have used (modifier)* in +// place of a call to modifiers, but I thought it was a good idea to keep +// this rule separate so they can easily be collected in a Vector if +// someone so desires +modifiers + : ( modifier )* + {#modifiers = #([MODIFIERS, "MODIFIERS"], #modifiers);} + ; // modifiers for Java classes, interfaces, class/instance vars and methods modifier @@ -205,11 +204,11 @@ modifier | "native" | "threadsafe" | "synchronized" -// | "const" // reserved word; leave out +// | "const" // reserved word, but not valid | "volatile" + | "strictfp" ; - // Definition of a Java class classDefinition![AST modifiers] : "class" IDENT @@ -275,7 +274,7 @@ implementsClause field! : // method, constructor, or variable declaration mods:modifiers - ( h:ctorHead s:compoundStatement // constructor + ( h:ctorHead s:constructorBody // constructor {#field = #(#[CTOR_DEF,"CTOR_DEF"], mods, h, s);} | cd:classDefinition[#mods] // inner class @@ -290,9 +289,10 @@ field! // parse the formal parameter declarations. LPAREN! param:parameterDeclarationList RPAREN! - rt:returnTypeBrackersOnEndOfMethodHead[#t] + rt:declaratorBrackets[#t] - // get the list of exceptions that this method is declared to throw + // get the list of exceptions that this method is + // declared to throw (tc:throwsClause)? ( s2:compoundStatement | SEMI ) @@ -318,6 +318,38 @@ field! {#field = #(#[INSTANCE_INIT,"INSTANCE_INIT"], s4);} ; +constructorBody + : lc:LCURLY^ {#lc.setType(SLIST);} + // Predicate might be slow but only checked once per constructor def + // not for general methods. + ( (explicitConstructorInvocation) => explicitConstructorInvocation + | + ) + (statement)* + RCURLY! + ; + +explicitConstructorInvocation + : ( options { + // this/super can begin a primaryExpression too; with finite + // lookahead ANTLR will think the 3rd alternative conflicts + // with 1, 2. I am shutting off warning since ANTLR resolves + // the nondeterminism by correctly matching alts 1 or 2 when + // it sees this( or super( + generateAmbigWarnings=false; + } + : "this"! lp1:LPAREN^ argList RPAREN! SEMI! + {#lp1.setType(CTOR_CALL);} + + | "super"! lp2:LPAREN^ argList RPAREN! SEMI! + {#lp2.setType(SUPER_CTOR_CALL);} + + // (new Outer()).super() (create enclosing instance) + | primaryExpression DOT! "super"! lp3:LPAREN^ argList RPAREN! SEMI! + {#lp3.setType(SUPER_CTOR_CALL);} + ) + ; + variableDefinitions[AST mods, AST t] : variableDeclarator[getASTFactory().dupTree(mods), getASTFactory().dupTree(t)] @@ -392,11 +424,6 @@ throwsClause ; -returnTypeBrackersOnEndOfMethodHead[AST typ] - : {#returnTypeBrackersOnEndOfMethodHead = typ;} - (lb:LBRACK^ {#lb.setType(ARRAY_DECLARATOR);} RBRACK!)* - ; - // A list of formal parameters parameterDeclarationList : ( parameterDeclaration ( COMMA! parameterDeclaration )* )? @@ -407,16 +434,11 @@ parameterDeclarationList // A formal parameter. parameterDeclaration! : pm:parameterModifier t:typeSpec[false] id:IDENT - pd:parameterDeclaratorBrackets[#t] + pd:declaratorBrackets[#t] {#parameterDeclaration = #(#[PARAMETER_DEF,"PARAMETER_DEF"], pm, #([TYPE,"TYPE"],pd), id);} ; -parameterDeclaratorBrackets[AST t] - : {#parameterDeclaratorBrackets = t;} - (lb:LBRACK^ {#lb.setType(ARRAY_DECLARATOR);} RBRACK!)* - ; - parameterModifier : (f:"final")? {#parameterModifier = #(#[MODIFIERS,"MODIFIERS"], f);} @@ -443,15 +465,6 @@ statement // A list of statements in curly braces -- start a new scope! : compoundStatement - // class definition - | classDefinition[#[MODIFIERS, "MODIFIERS"]] - - // final class definition - | "final"! classDefinition[#(#[MODIFIERS, "MODIFIERS"],#[FINAL,"final"])] - - // abstract class definition - | "abstract"! classDefinition[#(#[MODIFIERS, "MODIFIERS"],#[ABSTRACT,"abstract"])] - // declarations are ambiguous with "ID DOT" relative to expression // statements. Must backtrack to be sure. Could use a semantic // predicate to test symbol table to see what the type was coming @@ -463,6 +476,9 @@ statement // side-effects. | expression SEMI! + // class definition + | m:modifiers! classDefinition[#m] + // Attach a label to the front of a statement | IDENT c:COLON^ {#c.setType(LABELED_STAT);} statement @@ -651,9 +667,9 @@ assignmentExpression // conditional test (level 12) conditionalExpression - : logicalOrExpression - ( QUESTION^ assignmentExpression COLON conditionalExpression )? - ; + : logicalOrExpression + ( QUESTION^ assignmentExpression COLON! conditionalExpression )? + ; // logical or (||) (level 11) @@ -767,10 +783,10 @@ postfixExpression | "this" | "class" | newExpression - | "super" LPAREN ( expressionList )? RPAREN + | "super" // ClassName.super.field ) // the above line needs a semantic check to make sure "class" - // is the _last_ qualifier. + // is the _last_ qualifier. // allow ClassName[].class | ( lbc:LBRACK^ {#lbc.setType(ARRAY_DECLARATOR);} RBRACK! )+ @@ -784,6 +800,9 @@ postfixExpression // x[2](4) which are not valid in Java. If this grammar were used // to validate a Java program a semantic check would be needed, or // this rule would get really ugly... + // It also allows ctor invocation like super(3) which is now + // handled by the explicit constructor rule, but it would + // be hard to syntactically prevent ctor calls here | lp:LPAREN^ {#lp.setType(METHOD_CALL);} argList RPAREN! @@ -795,24 +814,23 @@ postfixExpression | de:DEC^ {#de.setType(POST_DEC);} | // nothing ) - - // look for int.class and int[].class - | builtInType - ( lbt:LBRACK^ {#lbt.setType(ARRAY_DECLARATOR);} RBRACK! )* - DOT^ "class" ; // the basic element of an expression primaryExpression : i1:IDENT {sFirstIdent = i1.getText();} - | newExpression | constant - | "super" | "true" | "false" | "this" | "null" + | newExpression | LPAREN! assignmentExpression RPAREN! + | "super" + // look for int.class and int[].class + | builtInType + ( lbt:LBRACK^ {#lbt.setType(ARRAY_DECLARATOR);} RBRACK! )* + DOT^ "class" ; /** object instantiation. @@ -909,6 +927,8 @@ constant | CHAR_LITERAL | STRING_LITERAL | NUM_FLOAT + | NUM_LONG + | NUM_DOUBLE ; @@ -921,7 +941,11 @@ options { exportVocab=GeneratedJava; // call the vocabulary "GeneratedJava" testLiterals=false; // don't automatically test for literals k=4; // four characters of lookahead -// charVocabulary='\u0003'..'\uFFFF'; + charVocabulary='\u0003'..'\uFFFF'; + // without inlining some bitset tests, couldn't do unicode; + // I need to make ANTLR generate smaller bitsets; see + // bottom of JavaLexer.java + codeGenBitsetTestThreshold=20; } @@ -979,13 +1003,14 @@ SEMI : ';' ; WS : ( ' ' | '\t' | '\f' - // handle newlines - | ( "\r\n" // Evil DOS + // handle newlines + | ( options {generateAmbigWarnings=false;} + : "\r\n" // Evil DOS | '\r' // Macintosh | '\n' // Unix (the right way) ) { newline(); } - ) + )+ { _ttype = Token.SKIP; } ; @@ -1117,9 +1142,19 @@ IDENT // a numeric literal NUM_INT - {boolean isDecimal=false;} - : '.' {_ttype = DOT;} - (('0'..'9')+ (EXPONENT)? (FLOAT_SUFFIX)? { _ttype = NUM_FLOAT; })? + {boolean isDecimal=false; Token t=null;} + : '.' {_ttype = DOT;} + ( ('0'..'9')+ (EXPONENT)? (f1:FLOAT_SUFFIX {t=f1;})? + { + if (t != null && t.getText().toUpperCase().indexOf('D')>=0) { + _ttype = NUM_DOUBLE; + } + else { + _ttype = NUM_FLOAT; + } + } + )? + | ( '0' {isDecimal = true;} // special case for just '0' ( ('x'|'X') ( // hex @@ -1137,16 +1172,23 @@ NUM_INT )? | ('1'..'9') ('0'..'9')* {isDecimal=true;} // non-zero decimal ) - ( ('l'|'L') + ( ('l'|'L') { _ttype = NUM_LONG; } // only check to see if it's a float if looks like decimal so far | {isDecimal}? - ( '.' ('0'..'9')* (EXPONENT)? (FLOAT_SUFFIX)? - | EXPONENT (FLOAT_SUFFIX)? - | FLOAT_SUFFIX - ) - { _ttype = NUM_FLOAT; } - )? + ( '.' ('0'..'9')* (EXPONENT)? (f2:FLOAT_SUFFIX {t=f2;})? + | EXPONENT (f3:FLOAT_SUFFIX {t=f3;})? + | f4:FLOAT_SUFFIX {t=f4;} + ) + { + if (t != null && t.getText().toUpperCase() .indexOf('D') >= 0) { + _ttype = NUM_DOUBLE; + } + else { + _ttype = NUM_FLOAT; + } + } + )? ; diff --git a/src/checkstyle/com/puppycrawl/tools/checkstyle/java.tree.g b/src/checkstyle/com/puppycrawl/tools/checkstyle/java.tree.g index 4e98a15af..89e6e38bd 100644 --- a/src/checkstyle/com/puppycrawl/tools/checkstyle/java.tree.g +++ b/src/checkstyle/com/puppycrawl/tools/checkstyle/java.tree.g @@ -117,6 +117,7 @@ modifier | "synchronized" | "const" | "volatile" + | "strictfp" ; extendsClause @@ -163,7 +164,7 @@ ctorDef MyModifierSet mods; MethodSignature ms; } - : #(CTOR_DEF mods=modifiers ms=methodHead {ver.reportStartMethodBlock();} slist {ver.reportEndMethodBlock();}) + : #(CTOR_DEF mods=modifiers ms=methodHead {ver.reportStartMethodBlock();} ctorSList {ver.reportEndMethodBlock();}) { ver.verifyMethodJavadoc(mods, null, ms); } @@ -293,6 +294,10 @@ identifierStar | #( DOT ignore=identifier (STAR|IDENT) ) ; +ctorSList + : #( SLIST (ctorCall)? (stat)* ) + ; + slist : #( SLIST (stat)* ) ; @@ -434,8 +439,9 @@ primaryExpression | "this" | "class" { if (firstExprIdent != null) { ver.reportReference(firstExprIdent.getText()); } } | #( "new" IDENT elist ) + | "super" ) - | #(ARRAY_DECLARATOR type) + | #(ARRAY_DECLARATOR typeSpecArray) | builtInType ("class")? ) ) @@ -452,6 +458,15 @@ primaryExpression | typeSpec // type name used with instanceof ; +ctorCall + : #( CTOR_CALL elist ) + | #( SUPER_CTOR_CALL + ( elist + | primaryExpression elist + ) + ) + ; + arrayIndex : #(INDEX_OP primaryExpression expression) ; @@ -461,6 +476,8 @@ constant | CHAR_LITERAL | STRING_LITERAL | NUM_FLOAT + | NUM_DOUBLE + | NUM_LONG ; newExpression