diff --git a/scope/src/main/jastadd/Navigation.jrag b/scope/src/main/jastadd/Navigation.jrag
new file mode 100644
index 0000000000000000000000000000000000000000..fa9e2a4d2eedc04e2a5df36bbb3fe3480725b88f
--- /dev/null
+++ b/scope/src/main/jastadd/Navigation.jrag
@@ -0,0 +1,13 @@
+aspect Navigation {
+  syn boolean Element.isScope() = false;
+  eq Scope.isScope() = true;
+
+  syn Scope Element.asScope() = null;
+  eq Scope.asScope() = this;
+
+  syn boolean Element.isDeclaration() = false;
+  eq Declaration.isDeclaration() = true;
+
+  syn Declaration Element.asDeclaration() = null;
+  eq Declaration.asDeclaration() = this;
+}
diff --git a/scope/src/main/jastadd/ScopeTree.relast b/scope/src/main/jastadd/ScopeTree.relast
new file mode 100644
index 0000000000000000000000000000000000000000..8ed72413754ad3fc998ac9d0e6e0f6a0caa4e435
--- /dev/null
+++ b/scope/src/main/jastadd/ScopeTree.relast
@@ -0,0 +1,4 @@
+ScopeTree : Scope;
+abstract Element;
+Declaration:Element ::= <Name:String>;
+Scope:Element ::= Element*;
diff --git a/scope/src/main/jastadd/Shadowing.jadd b/scope/src/main/jastadd/Shadowing.jadd
new file mode 100644
index 0000000000000000000000000000000000000000..b15f9f6f0d912cb31869f023a2575b127fe1d04d
--- /dev/null
+++ b/scope/src/main/jastadd/Shadowing.jadd
@@ -0,0 +1,5 @@
+aspect Shadowing {
+  public class VariableShadowFinding {
+    // add fields and getters/setters for shadowed and shadowing variable
+  }
+}
diff --git a/scope/src/main/jastadd/Shadowing.jrag b/scope/src/main/jastadd/Shadowing.jrag
new file mode 100644
index 0000000000000000000000000000000000000000..a079a0adea0876780e6823aec19d9e4c4153f7d9
--- /dev/null
+++ b/scope/src/main/jastadd/Shadowing.jrag
@@ -0,0 +1,26 @@
+aspect Shadowing {
+  coll Set<VariableShadowFinding> ScopeTree.variableShadowings() [new HashSet<>()] with add root ScopeTree;
+
+  syn int Scope.numScopes() {
+    int result = 1;
+    for (Element element : getElementList()) {
+      if (element.isScope()) {
+        result += element.asScope().numScopes();
+      }
+    }
+    return result;
+  }
+
+  syn int Scope.numDeclarations() {
+    int result = 0;
+    for (Element element : getElementList()) {
+      if (element.isScope()) {
+        result += element.asScope().numDeclarations();
+      } else {
+        result++;
+      }
+    }
+    return result;
+  }
+
+}
diff --git a/scope4j/.gitignore b/scope4j/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..d8bcc397b73edab07c3ab2e5b6a547424bf1c95a
--- /dev/null
+++ b/scope4j/.gitignore
@@ -0,0 +1,27 @@
+# Compiled class file
+*.class
+
+# Log file
+*.log
+
+# Package Files #
+*.jar
+*.war
+*.nar
+*.ear
+*.zip
+*.tar.gz
+*.rar
+
+# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
+hs_err_pid*
+
+out/
+*.iml
+/.idea/*
+!.idea/codeStyles
+!libs/relast.jar
+
+graph/
+src/gen/
+build/
diff --git a/scope4j/build.gradle b/scope4j/build.gradle
new file mode 100644
index 0000000000000000000000000000000000000000..74c3ca8b598d9fb9801d589d931b351e00ef7b25
--- /dev/null
+++ b/scope4j/build.gradle
@@ -0,0 +1,214 @@
+buildscript {
+    repositories.mavenLocal()
+    repositories.mavenCentral()
+    dependencies {
+        classpath 'org.jastadd:jastaddgradle:1.13.3'
+    }
+}
+
+apply plugin: 'java'
+apply plugin: 'application'
+apply plugin: 'jastadd'
+apply plugin: 'idea'
+
+repositories {
+    mavenLocal()
+}
+
+idea {
+    module {
+        generatedSourceDirs += file('./src/gen/java')
+        sourceDirs += file('../extendj/src/frontend')
+        sourceDirs += file('../extendj/src/frontend-main')
+    }
+}
+
+sourceSets.main {
+    java {
+
+        srcDirs "src/gen/java"
+        srcDirs '../extendj/src/frontend'
+        srcDirs '../extendj/src/frontend-main'
+    }
+    resources {
+        srcDir '../extendj/src/res'
+        srcDir jastadd.buildInfoDir
+    }
+}
+
+dependencies {
+}
+
+jastadd {
+    configureModuleBuild()
+
+    modules {
+
+        include("../extendj/jastadd_modules")
+
+        module "scope-analysis", {
+
+            imports "java8 frontend"
+
+            jastadd {
+                basedir ".."
+                include "scope4j/src/gen/jastadd/Java.ast"
+                include "scope4j/src/gen/jastadd/Java.jadd"
+                include "scope4j/src/main/jastadd/*.jrag"
+                include "scope4j/src/main/jastadd/*.jadd"
+                include "scope/src/main/jastadd/*.jrag"
+                include "scope/src/main/jastadd/*.jadd"
+
+                excludeFrom "java8 frontend", "grammar/ConstructorReference.ast"
+                excludeFrom "java8 frontend", "grammar/IntersectionCasts.ast"
+                excludeFrom "java8 frontend", "grammar/Lambda.ast"
+                excludeFrom "java8 frontend", "grammar/LambdaAnonymousDecl.ast"
+                excludeFrom "java8 frontend", "grammar/MethodReference.ast"
+                // excludeFrom "java7 frontend", "grammar/BasicTWR.ast"
+                excludeFrom "java7 frontend", "grammar/Diamond.ast"
+                excludeFrom "java7 frontend", "grammar/Literals.ast"
+                excludeFrom "java7 frontend", "grammar/MultiCatch.ast"
+                excludeFrom "java7 frontend", "grammar/TryWithResources.ast"
+                excludeFrom "java5 frontend", "grammar/Annotations.ast"
+                excludeFrom "java5 frontend", "grammar/EnhancedFor.ast"
+                excludeFrom "java5 frontend", "grammar/Enums.ast"
+                excludeFrom "java5 frontend", "grammar/GenericMethods.ast"
+                excludeFrom "java5 frontend", "grammar/Generics.ast"
+                excludeFrom "java5 frontend", "grammar/StaticImports.ast"
+                excludeFrom "java5 frontend", "grammar/VariableArityParameters.ast"
+                excludeFrom "java4 frontend", "grammar/BoundNames.ast"
+                excludeFrom "java4 frontend", "grammar/Java.ast"
+                excludeFrom "java4 frontend", "grammar/Literals.ast"
+                excludeFrom "java4 frontend", "grammar/NTAFinally.ast"
+
+                excludeFrom "java7 frontend", "frontend/JavaVersion.jrag"
+
+                excludeFrom "java5 frontend", "frontend/BytecodeReader.jrag"
+                excludeFrom "java7 frontend", "frontend/Variable.jadd"
+            }
+
+            java {
+                basedir "src/main/java/"
+                include "**/*.java"
+            }
+
+        }
+
+    }
+
+
+    // Target module to build:
+    module = 'scope-analysis'
+
+    astPackage = 'org.extendj.ast'
+    parser.name = 'JavaParser'
+    scanner.name = 'OriginalScanner'
+
+    genDir = 'src/gen/java'
+
+    parser.genDir = 'src/gen/java/org/extendj/parser'
+    scanner.genDir = 'src/gen/java/org/extendj/scanner'
+
+    parser.genDir = 'src/gen/java/org/extendj/parser'
+    scanner.genDir = 'src/gen/java/org/extendj/scanner'
+//
+//	if (project.hasProperty('extraJastAddOptions')) {
+//		extraJastAddOptions += project.extraJastAddOptions.split(',') as List
+//		print("options: ${extraJastAddOptions}")
+//	}
+
+//	jastaddOptions = [ "--rewrite=cnta", "--safeLazy", "--tracing=all" ]
+    jastaddOptions = ["--rewrite=cnta", "--safeLazy", "--tracing=api", "--visitCheck=false"]
+
+//	jastaddOptions = [ "--concurrent", "--rewrite=cnta", "--safeLazy" ]
+//	jastaddOptions = [ "--concurrent", "--rewrite=cnta", "--safeLazy", "--cache=all" ]
+}
+
+run {
+    mainClassName = 'org.extendj.SccChecker'
+    if (project.hasProperty("appArgs")) {
+        args Eval.me(appArgs)
+    }
+}
+
+task preprocess(type: JavaExec) {
+    group = 'Build'
+    main = "-jar"
+
+    doFirst {
+        delete "src/gen/jastadd"
+        mkdir "src/gen/jastadd"
+    }
+
+    args = [
+            "../tools/relast.jar",
+            "src/main/jastadd/ProgramToScopeTree.relast",
+            "../scope/src/main/jastadd/ScopeTree.relast",
+            "../extendj/java8/grammar/ConstructorReference.ast",
+            "../extendj/java8/grammar/IntersectionCasts.ast",
+            "../extendj/java8/grammar/Lambda.ast",
+            "../extendj/java8/grammar/LambdaAnonymousDecl.ast",
+            "../extendj/java8/grammar/MethodReference.ast",
+//			"../extendj/java7/grammar/BasicTWR.ast",
+            "../extendj/java7/grammar/Diamond.ast",
+            "../extendj/java7/grammar/Literals.ast",
+            "../extendj/java7/grammar/MultiCatch.ast",
+            "../extendj/java7/grammar/TryWithResources.ast",
+            "../extendj/java5/grammar/Annotations.ast",
+            "../extendj/java5/grammar/EnhancedFor.ast",
+            "../extendj/java5/grammar/Enums.ast",
+            "../extendj/java5/grammar/GenericMethods.ast",
+            "../extendj/java5/grammar/Generics.ast",
+            "../extendj/java5/grammar/StaticImports.ast",
+            "../extendj/java5/grammar/VariableArityParameters.ast",
+            "../extendj/java4/grammar/BoundNames.ast",
+            "../extendj/java4/grammar/Java.ast",
+            "../extendj/java4/grammar/Literals.ast",
+            "../extendj/java4/grammar/NTAFinally.ast",
+
+            "--listClass=ArrayList",
+//			"--jastAddList=JastAddList",
+//			"--serializer=jackson",
+            "--useJastAddNames",
+            "--file",
+//			"--resolverHelper",
+            "--grammarName=src/gen/jastadd/Java"
+    ]
+
+    inputs.files file("../extendj/java8/grammar/ConstructorReference.ast"),
+            file("src/main/jastadd/ProgramToScopeTree.relast"),
+            file("../scope/src/main/jastadd/ScopeTree.relast"),
+            file("../extendj/java8/grammar/IntersectionCasts.ast"),
+            file("../extendj/java8/grammar/Lambda.ast"),
+            file("../extendj/java8/grammar/LambdaAnonymousDecl.ast"),
+            file("../extendj/java8/grammar/MethodReference.ast"),
+            file("../extendj/java7/grammar/BasicTWR.ast"),
+            file("../extendj/java7/grammar/Diamond.ast"),
+            file("../extendj/java7/grammar/Literals.ast"),
+            file("../extendj/java7/grammar/MultiCatch.ast"),
+            file("../extendj/java7/grammar/TryWithResources.ast"),
+            file("../extendj/java5/grammar/Annotations.ast"),
+            file("../extendj/java5/grammar/EnhancedFor.ast"),
+            file("../extendj/java5/grammar/Enums.ast"),
+            file("../extendj/java5/grammar/GenericMethods.ast"),
+            file("../extendj/java5/grammar/Generics.ast"),
+            file("../extendj/java5/grammar/StaticImports.ast"),
+            file("../extendj/java5/grammar/VariableArityParameters.ast"),
+            file("../extendj/java4/grammar/BoundNames.ast"),
+            file("../extendj/java4/grammar/Java.ast"),
+            file("../extendj/java4/grammar/Literals.ast"),
+            file("../extendj/java4/grammar/NTAFinally.ast"),
+            file("../tools/relast.jar")
+    outputs.files file("src/gen/jastadd/Java.ast"),
+            file("src/gen/jastadd/Java.jadd")
+}
+
+
+generateAst.dependsOn preprocess
+
+mainClassName = 'org.extendj.ScopeAnalysis'
+jar.manifest.attributes 'Main-Class': mainClassName
+jar.destinationDir = projectDir
+
+sourceCompatibility = '1.8'
+targetCompatibility = '1.8'
diff --git a/scope4j/src/main/jastadd/ProgramToScopeTree.jrag b/scope4j/src/main/jastadd/ProgramToScopeTree.jrag
new file mode 100644
index 0000000000000000000000000000000000000000..6a578114c145410250ab53a930521e8408fc60a4
--- /dev/null
+++ b/scope4j/src/main/jastadd/ProgramToScopeTree.jrag
@@ -0,0 +1,7 @@
+aspect ProgramToScopeTree {
+  syn lazy ScopeTree Program.scopeTree() {
+    ScopeTree tree = new ScopeTree();
+    tree.setProgram(this);
+    return tree;
+  }
+}
diff --git a/scope4j/src/main/jastadd/ProgramToScopeTree.relast b/scope4j/src/main/jastadd/ProgramToScopeTree.relast
new file mode 100644
index 0000000000000000000000000000000000000000..435548d30833d65bf82061133e123e8e97d18eb4
--- /dev/null
+++ b/scope4j/src/main/jastadd/ProgramToScopeTree.relast
@@ -0,0 +1,2 @@
+// glue relation for the Java-based variable shadowing analysis
+rel ScopeTree.Program -> Program;
diff --git a/scope4j/src/main/jastadd/Shadow.jrag b/scope4j/src/main/jastadd/Shadow.jrag
new file mode 100644
index 0000000000000000000000000000000000000000..4052de87b00e4abdb7a4bb0d6ccc24632d30501c
--- /dev/null
+++ b/scope4j/src/main/jastadd/Shadow.jrag
@@ -0,0 +1,3 @@
+aspect Shadow {
+
+}
diff --git a/scope4j/src/main/java/org/extendj/JavaVariableShadowFinding.java b/scope4j/src/main/java/org/extendj/JavaVariableShadowFinding.java
new file mode 100644
index 0000000000000000000000000000000000000000..3a84d7982d36fb68d732b307e81ad6bb3d3a5243
--- /dev/null
+++ b/scope4j/src/main/java/org/extendj/JavaVariableShadowFinding.java
@@ -0,0 +1,7 @@
+package org.extendj;
+
+import org.extendj.ast.VariableShadowFinding;
+
+public class JavaVariableShadowFinding extends VariableShadowFinding {
+  // add getters for the actual Java structures
+}
diff --git a/scope4j/src/main/java/org/extendj/ScopeAnalysis.java b/scope4j/src/main/java/org/extendj/ScopeAnalysis.java
new file mode 100644
index 0000000000000000000000000000000000000000..b1b8298bae91d66ce7179a413b4e334d2b2ddf6e
--- /dev/null
+++ b/scope4j/src/main/java/org/extendj/ScopeAnalysis.java
@@ -0,0 +1,104 @@
+package org.extendj;
+
+
+import org.extendj.ast.*;
+
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.Collection;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+public class ScopeAnalysis extends Frontend {
+
+  public ScopeAnalysis() {
+    super("Java Scope Anaysis", ExtendJVersion.getVersion());
+  }
+
+
+  /**
+   * Entry point for the Java checker.
+   *
+   * @param args command-line arguments
+   */
+  public static void main(String[] args) {
+
+    if (args.length != 1) {
+      System.out.println("usage: SccChecker <directory with java files>");
+      System.exit(-1);
+    }
+
+    try {
+      List<String> files = Files.walk(Paths.get(args[2]))
+          .filter(Files::isRegularFile)
+          .filter(x -> x.getFileName().toString().endsWith(".java")).map(Path::toString).collect(Collectors.toList());
+
+      // measure the time (with parsing) from here
+      long startMeasurementTime = System.nanoTime();
+
+      Program program = new ScopeAnalysis().readProgram(files);
+
+      // measure the time (without parsing) from here
+      long startGenerationTime = System.nanoTime();
+
+      ScopeTree scopeTree = program.scopeTree();
+      long startAnalysisTime = System.nanoTime();
+
+      Set<VariableShadowFinding> findings = scopeTree.variableShadowings();
+
+      // measure the time until here
+      long endTime = System.nanoTime();
+
+      System.out.print("java,var,false,"
+          + files.size() + ","
+          + scopeTree.numScopes() + ","
+          + scopeTree.numDeclarations() + ","
+          + (scopeTree.numScopes() + scopeTree.numDeclarations()) + ","
+          + findings.size() + ",");
+
+      long parseTime = startGenerationTime - startMeasurementTime;
+      long generationTime = startAnalysisTime - startGenerationTime;
+      long analysisTime = endTime - startAnalysisTime;
+      long fullTime = endTime - startMeasurementTime;
+
+      System.out.print((fullTime / 1000000) + ",");
+      System.out.print((parseTime / 1000000) + ",");
+      System.out.print((generationTime / 1000000) + ",");
+      System.out.print((analysisTime / 1000000) + ",");
+      System.out.print(((generationTime + analysisTime) / 1000000) + ",");
+
+
+    } catch (IOException e) {
+      throw new RuntimeException(e);
+    }
+  }
+
+  private Program readProgram(Collection<String> files) throws IOException {
+
+
+    Program program = new Program();
+    program.resetStatistics();
+    program.initBytecodeReader(Program.defaultBytecodeReader());
+    program.initJavaParser(Program.defaultJavaParser());
+
+    initOptions();
+
+    for (String file : files) {
+      program.addSourceFile(file);
+    }
+
+    TypeDecl object = program.lookupType("java.lang", "Object");
+    if (object.isUnknown()) {
+      // If we try to continue without java.lang.Object, we'll just get a stack overflow
+      // in member lookups because the unknown (Object) type would be treated as circular.
+      System.err.println("Error: java.lang.Object is missing."
+          + " The Java standard library was not found.");
+      throw new RuntimeException("exiting with unhandled error!");
+    }
+
+    return program;
+  }
+}
diff --git a/settings.gradle b/settings.gradle
index 3b700667808a170cc263f25962885139a6f818eb..2dfdf27bc1b453580ff1fb73ceffd364c95c8bb5 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -10,10 +10,12 @@
 rootProject.name = 'relast-reuse'
 
 include 'statemachine'
-include 'dg'
-include 'simplecfg'
 include 'extendj'
+include 'dg'
 include 'deps4j'
+include 'scope'
+include 'scope4j'
+include 'simplecfg'
 include 'extendj:java4'
 include 'extendj:java5'
 include 'extendj:java6'