diff --git a/benchmarks/src/main/kotlin/org/Performance.kt b/benchmarks/src/main/kotlin/org/Performance.kt
new file mode 100644
index 000000000..9d886c027
--- /dev/null
+++ b/benchmarks/src/main/kotlin/org/Performance.kt
@@ -0,0 +1,403 @@
+package org
+
+import org.ucfs.input.LinearInputLabel
+import org.ucfs.sppf.node.SppfNode
+
+class Performance {}
+val code =
+ """package org.junit.experimental.categories;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+
+import org.junit.runner.Description;
+import org.junit.runner.manipulation.Filter;
+import org.junit.runner.manipulation.NoTestsRemainException;
+import org.junit.runners.Suite;
+import org.junit.runners.model.InitializationError;
+import org.junit.runners.model.RunnerBuilder;
+
+/**
+ * From a given set of test classes, runs only the classes and methods that are
+ * annotated with either the category given with the @IncludeCategory
+ * annotation, or a subtype of that category.
+ *
+ * Note that, for now, annotating suites with {@code @Category} has no effect.
+ * Categories must be annotated on the direct method or class.
+ *
+ * Example:
+ *
+ * public interface FastTests {
+ * }
+ *
+ * public interface SlowTests {
+ * }
+ *
+ * public interface SmokeTests
+ * }
+ *
+ * public static class A {
+ * @Test
+ * public void a() {
+ * fail();
+ * }
+ *
+ * @Category(SlowTests.class)
+ * @Test
+ * public void b() {
+ * }
+ *
+ * @Category({FastTests.class, SmokeTests.class})
+ * @Test
+ * public void c() {
+ * }
+ * }
+ *
+ * @Category({SlowTests.class, FastTests.class})
+ * public static class B {
+ * @Test
+ * public void d() {
+ * }
+ * }
+ *
+ * @RunWith(Categories.class)
+ * @IncludeCategory(SlowTests.class)
+ * @SuiteClasses({A.class, B.class})
+ * // Note that Categories is a kind of Suite
+ * public static class SlowTestSuite {
+ * // Will run A.b and B.d, but not A.a and A.c
+ * }
+ *
+ *
+ * Example to run multiple categories:
+ *
+ * @RunWith(Categories.class)
+ * @IncludeCategory({FastTests.class, SmokeTests.class})
+ * @SuiteClasses({A.class, B.class})
+ * public static class FastOrSmokeTestSuite {
+ * // Will run A.c and B.d, but not A.b because it is not any of FastTests or SmokeTests
+ * }
+ *
+ *
+ * @version 4.12
+ * @see Categories at JUnit wiki
+ */
+public class Categories extends Suite {
+
+ @Retention(RetentionPolicy.RUNTIME)
+ public @interface IncludeCategory {
+ /**
+ * Determines the tests to run that are annotated with categories specified in
+ * the value of this annotation or their subtypes unless excluded with {@link ExcludeCategory}.
+ */
+ public Class>[] value() default {};
+
+ /**
+ * If true, runs tests annotated with any of the categories in
+ * {@link IncludeCategory#value()}. Otherwise, runs tests only if annotated with all of the categories.
+ */
+ public boolean matchAny() default true;
+ }
+
+ @Retention(RetentionPolicy.RUNTIME)
+ public @interface ExcludeCategory {
+ /**
+ * Determines the tests which do not run if they are annotated with categories specified in the
+ * value of this annotation or their subtypes regardless of being included in {@link IncludeCategory#value()}.
+ */
+ public Class>[] value() default {};
+
+ /**
+ * If true, the tests annotated with any of the categories in {@link ExcludeCategory#value()}
+ * do not run. Otherwise, the tests do not run if and only if annotated with all categories.
+ */
+ public boolean matchAny() default true;
+ }
+
+ public static class CategoryFilter extends Filter {
+ private final Set> included;
+ private final Set> excluded;
+ private final boolean includedAny;
+ private final boolean excludedAny;
+
+ public static CategoryFilter include(boolean matchAny, Class>... categories) {
+ if (hasNull(categories)) {
+ throw new NullPointerException("has null category");
+ }
+ return categoryFilter(matchAny, createSet(categories), true, null);
+ }
+
+ public static CategoryFilter include(Class> category) {
+ return include(true, category);
+ }
+
+ public static CategoryFilter include(Class>... categories) {
+ return include(true, categories);
+ }
+
+ public static CategoryFilter exclude(boolean matchAny, Class>... categories) {
+ if (hasNull(categories)) {
+ throw new NullPointerException("has null category");
+ }
+ return categoryFilter(true, null, matchAny, createSet(categories));
+ }
+
+ public static CategoryFilter exclude(Class> category) {
+ return exclude(true, category);
+ }
+
+ public static CategoryFilter exclude(Class>... categories) {
+ return exclude(true, categories);
+ }
+
+ public static CategoryFilter categoryFilter(boolean matchAnyInclusions, Set> inclusions,
+ boolean matchAnyExclusions, Set> exclusions) {
+ return new CategoryFilter(matchAnyInclusions, inclusions, matchAnyExclusions, exclusions);
+ }
+
+ protected CategoryFilter(boolean matchAnyIncludes, Set> includes,
+ boolean matchAnyExcludes, Set> excludes) {
+ includedAny = matchAnyIncludes;
+ excludedAny = matchAnyExcludes;
+ included = copyAndRefine(includes);
+ excluded = copyAndRefine(excludes);
+ }
+
+ /**
+ * @see #toString()
+ */
+ @Override
+ public String describe() {
+ return toString();
+ }
+
+ /**
+ * Returns string in the form "[included categories] - [excluded categories]", where both
+ * sets have comma separated names of categories.
+ *
+ * @return string representation for the relative complement of excluded categories set
+ * in the set of included categories. Examples:
+ *
+ * - "categories [all]" for all included categories and no excluded ones;
+ *
- "categories [all] - [A, B]" for all included categories and given excluded ones;
+ *
- "categories [A, B] - [C, D]" for given included categories and given excluded ones.
+ *
+ * @see Class#toString() name of category
+ */
+ @Override public String toString() {
+ StringBuilder description= new StringBuilder("categories ")
+ .append(included.isEmpty() ? "[all]" : included);
+ if (!excluded.isEmpty()) {
+ description.append(" - ").append(excluded);
+ }
+ return description.toString();
+ }
+
+ @Override
+ public boolean shouldRun(Description description) {
+ if (hasCorrectCategoryAnnotation(description)) {
+ return true;
+ }
+
+ for (Description each : description.getChildren()) {
+ if (shouldRun(each)) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ private boolean hasCorrectCategoryAnnotation(Description description) {
+ final Set> childCategories= categories(description);
+
+ // If a child has no categories, immediately return.
+ if (childCategories.isEmpty()) {
+ return included.isEmpty();
+ }
+
+ if (!excluded.isEmpty()) {
+ if (excludedAny) {
+ if (matchesAnyParentCategories(childCategories, excluded)) {
+ return false;
+ }
+ } else {
+ if (matchesAllParentCategories(childCategories, excluded)) {
+ return false;
+ }
+ }
+ }
+
+ if (included.isEmpty()) {
+ // Couldn't be excluded, and with no suite's included categories treated as should run.
+ return true;
+ } else {
+ if (includedAny) {
+ return matchesAnyParentCategories(childCategories, included);
+ } else {
+ return matchesAllParentCategories(childCategories, included);
+ }
+ }
+ }
+
+ /**
+ * @return true if at least one (any) parent category match a child, otherwise false.
+ * If empty parentCategories, returns false.
+ */
+ private boolean matchesAnyParentCategories(Set> childCategories, Set> parentCategories) {
+ for (Class> parentCategory : parentCategories) {
+ if (hasAssignableTo(childCategories, parentCategory)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * @return false if at least one parent category does not match children, otherwise true.
+ * If empty parentCategories, returns true.
+ */
+ private boolean matchesAllParentCategories(Set> childCategories, Set> parentCategories) {
+ for (Class> parentCategory : parentCategories) {
+ if (!hasAssignableTo(childCategories, parentCategory)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ private static Set> categories(Description description) {
+ Set> categories= new HashSet>();
+ Collections.addAll(categories, directCategories(description));
+ Collections.addAll(categories, directCategories(parentDescription(description)));
+ return categories;
+ }
+
+ private static Description parentDescription(Description description) {
+ Class> testClass= description.getTestClass();
+ return testClass == null ? null : Description.createSuiteDescription(testClass);
+ }
+
+ private static Class>[] directCategories(Description description) {
+ if (description == null) {
+ return new Class>[0];
+ }
+
+ Category annotation= description.getAnnotation(Category.class);
+ return annotation == null ? new Class>[0] : annotation.value();
+ }
+
+ private static Set> copyAndRefine(Set> classes) {
+ HashSet> c= new HashSet>();
+ if (classes != null) {
+ c.addAll(classes);
+ }
+ c.remove(null);
+ return c;
+ }
+
+ private static boolean hasNull(Class>... classes) {
+ if (classes == null) return false;
+ for (Class> clazz : classes) {
+ if (clazz == null) {
+ return true;
+ }
+ }
+ return false;
+ }
+ }
+
+ public Categories(Class> klass, RunnerBuilder builder) throws InitializationError {
+ super(klass, builder);
+ try {
+ Set> included= getIncludedCategory(klass);
+ Set> excluded= getExcludedCategory(klass);
+ boolean isAnyIncluded= isAnyIncluded(klass);
+ boolean isAnyExcluded= isAnyExcluded(klass);
+
+ filter(CategoryFilter.categoryFilter(isAnyIncluded, included, isAnyExcluded, excluded));
+ } catch (NoTestsRemainException e) {
+ throw new InitializationError(e);
+ }
+ assertNoCategorizedDescendentsOfUncategorizeableParents(getDescription());
+ }
+
+ private static Set> getIncludedCategory(Class> klass) {
+ IncludeCategory annotation= klass.getAnnotation(IncludeCategory.class);
+ return createSet(annotation == null ? null : annotation.value());
+ }
+
+ private static boolean isAnyIncluded(Class> klass) {
+ IncludeCategory annotation= klass.getAnnotation(IncludeCategory.class);
+ return annotation == null || annotation.matchAny();
+ }
+
+ private static Set> getExcludedCategory(Class> klass) {
+ ExcludeCategory annotation= klass.getAnnotation(ExcludeCategory.class);
+ return createSet(annotation == null ? null : annotation.value());
+ }
+
+ private static boolean isAnyExcluded(Class> klass) {
+ ExcludeCategory annotation= klass.getAnnotation(ExcludeCategory.class);
+ return annotation == null || annotation.matchAny();
+ }
+
+ private static void assertNoCategorizedDescendentsOfUncategorizeableParents(Description description) throws InitializationError {
+ if (!canHaveCategorizedChildren(description)) {
+ assertNoDescendantsHaveCategoryAnnotations(description);
+ }
+ for (Description each : description.getChildren()) {
+ assertNoCategorizedDescendentsOfUncategorizeableParents(each);
+ }
+ }
+
+ private static void assertNoDescendantsHaveCategoryAnnotations(Description description) throws InitializationError {
+ for (Description each : description.getChildren()) {
+ if (each.getAnnotation(Category.class) != null) {
+ throw new InitializationError("Category annotations on Parameterized classes are not supported on individual methods.");
+ }
+ assertNoDescendantsHaveCategoryAnnotations(each);
+ }
+ }
+
+ // If children have names like [0], our current magical category code can't determine their parentage.
+ private static boolean canHaveCategorizedChildren(Description description) {
+ for (Description each : description.getChildren()) {
+ if (each.getTestClass() == null) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ private static boolean hasAssignableTo(Set> assigns, Class> to) {
+ for (final Class> from : assigns) {
+ if (to.isAssignableFrom(from)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private static Set> createSet(Class>... t) {
+ final Set> set= new HashSet>();
+ if (t != null) {
+ Collections.addAll(set, t);
+ }
+ return set;
+ }
+}
+"""
+fun main() {
+ for (i in 0..2_000)
+ parse(code)
+}
+
+fun parse(code: String): SppfNode? {
+ val parser = org.ucfs.Java8Parser()
+ parser.setInput(getTokenStream(code))
+ return parser.parse().first
+}
\ No newline at end of file
diff --git a/scripts/generate_all.sh b/scripts/generate_all.sh
index 2dd7e7437..26d67f426 100755
--- a/scripts/generate_all.sh
+++ b/scripts/generate_all.sh
@@ -3,7 +3,7 @@ shopt -s nullglob #ingore failed patterns
rootPrj=$(pwd)
parserDest="../benchmarks/src/main/kotlin/"
antlrSrc="benchmarks/src/main/java/org/antlr"
-lexerSrc="examples/src/main/java/java7"
+lexerSrc="examples/src/main/java/java8"
printf "\n\nINSTALL PACKAGES\n"
apt-get install jflex