diff --git a/src/main/javacc/Java1.1.jj b/src/main/javacc/Java1.1.jj index ba0697b..e335f89 100644 --- a/src/main/javacc/Java1.1.jj +++ b/src/main/javacc/Java1.1.jj @@ -215,6 +215,7 @@ public class JavaParser implements JavaParserInterface public static final int TRANSIENT = 0x0100; public static final int VOLATILE = 0x0200; public static final int STRICTFP = 0x1000; + public static final int DEFAULT = 0x2000; /** A set of accessors that indicate whether the specified modifier is in the set. */ @@ -259,6 +260,11 @@ public class JavaParser implements JavaParserInterface return (modifiers & STRICTFP) != 0; } + public boolean isDefault(int modifiers) + { + return (modifiers & DEFAULT) != 0; + } + public boolean isSynchronized(int modifiers) { return (modifiers & SYNCHRONIZED) != 0; @@ -282,6 +288,36 @@ public class JavaParser implements JavaParserInterface return modifiers & ~mod; } } + + public static void main(String args[]) { + JavaParser parser; + if (args.length == 0) { + System.out.println("Java Parser Version 1.1: Reading from standard input . . ."); + parser = new JavaParser(System.in); + } else if (args.length == 1) { + System.out.println("Java Parser Version 1.1: Reading from file " + args[0] + " . . ."); + try { + parser = new JavaParser(new java.io.FileInputStream(args[0])); + } catch (java.io.FileNotFoundException e) { + System.out.println("Java Parser Version 1.1: File " + args[0] + " not found."); + return; + } + } else { + System.out.println("Java Parser Version 1.1: Usage is one of:"); + System.out.println(" java javancss.parser.JavaParser < inputfile"); + System.out.println("OR"); + System.out.println(" java javancss.parser.JavaParser inputfile"); + return; + } + try { + parser.CompilationUnit(); + System.out.println("Java Parser Version 1.1: Java program parsed successfully."); + } catch (ParseException e) { + System.out.println(e.getMessage()); + System.out.println("Java Parser Version 1.1: Encountered errors during parse."); + } + } + } PARSER_END(JavaParser) @@ -808,6 +844,8 @@ TOKEN : | < COMMA: "," > | < DOT: "." > | < AT: "@" > +| < LAMBDA: "->" > +| < DOUBLECOLON: "::" > } /* OPERATORS */ @@ -1357,7 +1395,7 @@ void ClassBodyDeclaration() : void MethodDeclarationLookahead() : {} { - ( "public" | "protected" | "private" | "static" | "abstract" | "final" | "native" | "synchronized" | "strictfp" | Annotation() )* + ( "public" | "protected" | "private" | "static" | "abstract" | "final" | "native" | "synchronized" | "strictfp" | "default" | Annotation() )* [ TypeParameters() ] ResultType() Identifier() "(" } @@ -1793,6 +1831,12 @@ void MethodDeclaration() : } } | "strictfp" + { + if ( tmpToken == null ) { + tmpToken = getToken( 0 ); + } + } +| "default" { if ( tmpToken == null ) { tmpToken = getToken( 0 ); @@ -2282,7 +2326,14 @@ void Expression() : //System.out.println( "Expression start" ); } { + LOOKAHEAD(LambdaExpression()) LambdaExpression() +| + AssignmentExpression() +} +void AssignmentExpression() : +{} +{ LOOKAHEAD( PrimaryExpression() AssignmentOperator() ) //{ System.out.println( "Expression" ); } Assignment() @@ -2464,6 +2515,8 @@ void CastExpression() : { LOOKAHEAD("(" PrimitiveType()) "(" Type() ")" UnaryExpression() +| + LOOKAHEAD("(" Type() ")" LambdaExpression()) "(" Type() ")" LambdaExpression() | "(" Type() ")" UnaryExpressionNotPlusMinus() } @@ -2473,6 +2526,8 @@ void PrimaryExpression() : // { System.out.println( "Before PrimaryExpression" ); } } { + LOOKAHEAD(MethodReference()) MethodReference() +| PrimaryPrefix() ( LOOKAHEAD(2) PrimarySuffix() )* } @@ -2521,7 +2576,7 @@ void PrimarySuffix() : // { System.out.println( "PrimarySuffix . Identifier()" ); } "." Identifier() | - Arguments() + Arguments() [ "{" MethodDeclaration() "}"] } void Literal() : @@ -2781,11 +2836,27 @@ void SwitchStatement() : _localCases = 0; } "switch" "(" Expression() ")" "{" - ( SwitchLabel() ( BlockStatement() )* )* + (SwitchCase())* "}" { _ncss++; Util.debug( "_ncss++" );} } +void SwitchCase() : +{} +{ + SwitchLabel() SwitchBlockStatements() +} + +void SwitchBlockStatements() : +{} +{ + LOOKAHEAD(SwitchLabel()) {} +| + BlockStatement() SwitchBlockStatements() +| + {} +} + void SwitchLabel() : {} { @@ -2800,7 +2871,7 @@ void SwitchLabel() : "default" ":" { _ncss++; Util.debug( "_ncss++" ); - } +} } void IfStatement() : @@ -2933,7 +3004,7 @@ void TryWithResources() : {} { // LocalVariableDeclaration() [ ";" ] - LocalVariableDeclaration() ( ";" LocalVariableDeclaration() )* + LocalVariableDeclaration() ( LOOKAHEAD(2) ";" LocalVariableDeclaration() )* [ ";" ] } void Identifier() : @@ -3140,6 +3211,11 @@ int Modifiers(): "strictfp" { modifiers |= ModifierSet.STRICTFP; if ( _tmpToken == null ) { _tmpToken = getToken( 0 ); } +} + | + "default" { modifiers |= ModifierSet.DEFAULT; if ( _tmpToken == null ) { + _tmpToken = getToken( 0 ); + } } | Annotation() @@ -3443,3 +3519,47 @@ void MemberSelector(): "." TypeArguments() } +void LambdaExpression(): +{} +{ + LambdaParameters() "->" LambdaBody() +} + +void LambdaParameters(): +{} +{ + +| + LOOKAHEAD("(" InferredFormalParameterList() ")") "(" InferredFormalParameterList() ")" +| + LOOKAHEAD( [FormalParameters()] ) [FormalParameters()] +} + +void InferredFormalParameterList(): +{} +{ + ( "," )* +} + + +void LambdaBody(): +{} +{ + Expression() +| + Block() +} + +void MethodReference(): +{} +{ + "super" "::" [TypeArguments()] +| + LOOKAHEAD( 4 ) Name() "." "super" "::" [TypeArguments()] +| +// ClassType() "::" [TypeArguments()] "new" and ArrayType() "::" "new" is included in below + LOOKAHEAD(ReferenceType() "::" [TypeArguments()] ( | "new" )) ReferenceType() "::" [TypeArguments()] ( | "new" ) +| +// Name() "::" [TypeArguments()] is included in below + PrimaryPrefix() ( LOOKAHEAD(2) PrimarySuffix() )* "::" [TypeArguments()] +} diff --git a/src/test/java/javancss/test/ParseTest.java b/src/test/java/javancss/test/ParseTest.java index 3e869b4..af898ef 100644 --- a/src/test/java/javancss/test/ParseTest.java +++ b/src/test/java/javancss/test/ParseTest.java @@ -60,7 +60,10 @@ private void testParse() _checkParse( 155 ); // JAVANCSS-28 _checkParse( 156 ); // hexadecimal floating-point literals _checkParse( 157 ); // Java 7 literals - _checkParse( 158 ); // JAVANCSS-48 + _checkParse(158); // JAVANCSS-48 + _checkParse(159); // default and static method in interface + _checkParse(160); // java8 lambda and method reference + _checkParse(161); // found by cobertura _exitSubTest(); } diff --git a/src/test/resources/Test148.java b/src/test/resources/Test148.java index 7829598..d9a1309 100644 --- a/src/test/resources/Test148.java +++ b/src/test/resources/Test148.java @@ -33,6 +33,23 @@ public void baz() { // do nothing } } + + public void baz2() { + String zipFileName = ""; + String outputFileName = ""; + java.nio.charset.Charset charset = java.nio.charset.Charset.forName("US-ASCII"); + java.nio.file.Path outputFilePath = java.nio.file.Paths.get(outputFileName); + + try ( + java.util.zip.ZipFile zf = new java.util.zip.ZipFile(zipFileName); + java.io.BufferedWriter writer = java.nio.file.Files.newBufferedWriter(outputFilePath, charset); + ) { + // do nothing + } + catch (java.beans.PropertyVetoException e) { + // do nothing + } + } } diff --git a/src/test/resources/Test159.java b/src/test/resources/Test159.java new file mode 100644 index 0000000..72c983e --- /dev/null +++ b/src/test/resources/Test159.java @@ -0,0 +1,9 @@ +interface Interface1 { + static void staticTest(String str) { + System.out.println(str); + } + + default int defaultTest() { + return 1; + } +} diff --git a/src/test/resources/Test160.java b/src/test/resources/Test160.java new file mode 100644 index 0000000..41017ef --- /dev/null +++ b/src/test/resources/Test160.java @@ -0,0 +1,141 @@ +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Iterator; +import java.util.List; +import java.util.function.Consumer; +import java.util.function.Function; +import java.util.function.IntBinaryOperator; +import java.util.function.IntFunction; +import java.util.function.IntSupplier; +import java.util.function.LongSupplier; +import java.util.function.Supplier; +import java.util.function.ToIntFunction; +import java.util.function.UnaryOperator; + +class MyList extends ArrayList { + + public MyList replaceAll2(UnaryOperator operator) { + return this; + } +} + +class T { + + public void tvarMember() { + } +} + +class Foo { + + public void bar() { + } + + static class Bar { + } + +} + +class R { + + R() { + } + + R(Integer a) { + } + + R(String a) { + } +} + +public class LamdasAndMethodRefs { + + public LamdasAndMethodRefs() { + //Method references + Runnable a = super::toString; + Runnable b = LamdasAndMethodRefs.super::toString; + } + + public static void main(String[] args) { + //Method references + LongSupplier a = System::currentTimeMillis; // static method + ToIntFunction b = String::length; // instance method + ToIntFunction c = List::size; + ToIntFunction> d = List::size; // explicit type arguments for generic type + UnaryOperator e = int[]::clone; + Consumer f = T::tvarMember; + + Runnable g = System.out::println; + Consumer h = String::valueOf; // overload resolution needed + IntSupplier i = "abc"::length; + Consumer j = Arrays::sort; // type arguments inferred from context + Consumer k = Arrays::sort; // explicit type arguments + Supplier> l = ArrayList::new; // constructor for parameterized type + Supplier m = ArrayList::new; // inferred type arguments + IntFunction n = int[]::new; // array creation + Supplier o = Foo::new; // explicit type arguments + Supplier p = Foo.Bar::new; // inner class constructor + Supplier> q = R::new; // generic class, generic constructor + + Foo[] foo = new Foo[2]; + int r = 1; + foo[r] = new Foo(); + Runnable s = foo[r]::bar; + boolean test = false; + MyList list = new MyList<>(); + Supplier> fun = (test ? list.replaceAll2(String::trim) : list)::iterator; + + // Lamdas + Runnable t = () -> { + }; // No parameters; result is void + IntSupplier u = () -> 42; // No parameters, expression body + Supplier v = () -> null; // No parameters, expression body + v = () -> { + return 42; + }; // No parameters, block body with return + t = () -> { + System.gc(); + }; // No parameters, void block body + v = () -> { // Complex block body with returns + if (true) { + return 12; + } + else { + int result = 15; + for (int i2 = 1; i2 < 10; i2++) { + result *= i2; + } + return result; + } + }; + IntFunction w = (int x) -> x + 1; // Single declared-type parameter + w = (int x) -> { + return x + 1; + }; // Single declared-type parameter + w = (x) -> x + 1; // Single inferred-type parameter + w = x -> x + 1; // Parentheses optional for + // single inferred-type parameter + Function z = (String s2) -> s2.length(); // Single declared-type parameter + Consumer a2 = (Thread t2) -> { + t2.start(); + }; // Single declared-type parameter + z = s3 -> s3.length(); // Single inferred-type parameter + a2 = t3 -> { + t3.start(); + }; // Single inferred-type parameter + IntBinaryOperator b2 = (int x, int y) -> x + y; // Multiple declared-type parameters + b2 = (x, y) -> x + y; // Multiple inferred-type parameters + + List myList + = Arrays.asList("a1", "a2", "b1", "c2", "c1"); + + myList.stream().filter((s4) -> { + System.out.println("filter " + s4); + return s4.startsWith("c"); + }).map(String::toUpperCase).sorted().forEach( + System.out::println); + + Runnable runnable = (Runnable)() -> System.out.println("Test"); + + } + +} \ No newline at end of file diff --git a/src/test/resources/Test161.java b/src/test/resources/Test161.java new file mode 100644 index 0000000..3281af6 --- /dev/null +++ b/src/test/resources/Test161.java @@ -0,0 +1,21 @@ + + package mypackage; + + public class FooMain { + public class Outer { + private Inner inner; + public Outer() { + inner = this.new Inner() { + @Override + public int getI() { + return 15; + } + }; + } + private class Inner { + public int getI() { + return 1; + } + } + } + } \ No newline at end of file