Skip to content
Snippets Groups Projects
Commit 5d4b1506 authored by Johannes Mey's avatar Johannes Mey
Browse files

Merge branch 'mquat2' into 'master'

Mquat2

Closes #11, #6, and #5

See merge request johannes.mey/relast!1
parents 6cbd6486 3872f912
No related branches found
No related tags found
1 merge request!1Mquat2
Pipeline #3456 passed
Showing
with 810 additions and 1376 deletions
.DS_Store
*.jar
.idea/
.gradle/
build
src/gen-res/
src/gen/
out/
*.class
.vimrc
.*.swp
/*.relast
/.settings
/bin/
/ant-bin/
/relast-compiler.jar
/src/generated/
/.gradle
/.idea/
*.iml
src/test/jastadd/*/*.ast
src/test/jastadd/*/*.jadd
src/test/jastadd/*/*ResolverStubs.jrag
!src/test/jastadd/*/MyRefResolver.jadd
stages:
- build
test:
image: openjdk:8
stage: build
script:
- ./gradlew --no-daemon build
......@@ -2,13 +2,14 @@
Run preprocessor on train benchmark (output written to standard output):
$ ant jar
$ ./gradlew jar
$ cat examples/TrainBenchmark.relast
$ java -jar relast-compiler.jar examples/TrainBenchmark.relast
$ java -jar build/libs/relast.jar examples/TrainBenchmark.relast
Run preprocessor and write output to files:
$ java -jar relast-compiler.jar examples/TrainBenchmark.relast --file
$ java -jar build/libs/relast.jar examples/TrainBenchmark.relast --file
$ cat examples/TrainBenchmarkGen.ast
$ cat examples/TrainBenchmarkGen.jadd
......
import org.jastadd.relast.plugin.RelastTest
apply plugin: 'java'
apply plugin: 'jastadd'
apply plugin: 'application'
apply plugin: "idea"
apply plugin: "org.jastadd.relast.plugin"
sourceCompatibility = 1.8
mainClassName = 'org.jastadd.relast.compiler.Compiler'
repositories {
jcenter()
}
buildscript {
repositories.jcenter()
dependencies {
classpath 'org.jastadd:jastaddgradle:1.13.3'
}
}
dependencies {
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.4.0'
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.4.0'
testCompile 'org.assertj:assertj-core:3.12.1'
compile 'com.fasterxml.jackson.core:jackson-core:2.9.8'
compile 'com.fasterxml.jackson.core:jackson-databind:2.9.8'
runtime 'org.jastadd:jastadd:2.3.2'
compile group: 'net.sf.beaver', name: 'beaver-rt', version: '0.9.11'
compile group: 'org.apache.logging.log4j', name: 'log4j-api', version: '2.10.0'
compile group: 'org.apache.logging.log4j', name: 'log4j-core', version: '2.10.0'
}
sourceSets {
main {
java.srcDir "src/gen/java"
java.srcDir "buildSrc/gen/java"
}
test {
java.srcDir "src/test/java-gen"
}
}
jar {
manifest {
attributes "Main-Class": 'org.jastadd.relast.compiler.Compiler'
}
from {
configurations.compile.collect { it.isDirectory() ? it : zipTree(it) }
}
}
jastadd {
configureModuleBuild()
modules {
//noinspection GroovyAssignabilityCheck
module("RelAst") {
java {
basedir "."
include "src/main/**/*.java"
include "src/gen/**/*.java"
}
jastadd {
basedir "src/main/jastadd/"
include "**/*.ast"
include "**/*.jadd"
include "**/*.jrag"
}
scanner {
include "src/main/jastadd/RelAst.flex"
}
parser {
include "src/main/jastadd/Preamble.parser"
include "src/main/jastadd/RelAst.parser"
}
}
}
cleanGen.doFirst {
delete "src/gen/java/org"
delete "src/gen-res/BuildInfo.properties"
}
preprocessParser.doFirst {
args += ["--no-beaver-symbol"]
}
module = "RelAst"
astPackage = 'org.jastadd.relast.ast'
parser.name = 'RelAstParser'
genDir = 'src/gen/java'
buildInfoDir = 'src/gen-res'
scanner.genDir = "src/gen/java/org/jastadd/relast/scanner"
parser.genDir = "src/gen/java/org/jastadd/relast/parser"
jastaddOptions = ["--lineColumnNumbers", "--safeLazy", "--visitCheck=true", "--rewrite=cnta", "--cache=all"]
}
task preprocessRelationTest(type: JavaExec, group: 'verification') {
doFirst {
delete 'src/test/jastadd/relations/Relations.ast', 'src/test/jastadd/relations/Relations.jadd'
}
classpath = sourceSets.main.runtimeClasspath
main = 'org.jastadd.relast.compiler.Compiler'
//noinspection GroovyAssignabilityCheck
args 'src/test/jastadd/relations/Relations.relast', '--useJastAddNames', '--file', '--grammarName=src/test/jastadd/relations/Relations'
}
task doublePreprocessRelationTest(type: JavaExec, group: 'verification') {
doFirst {
delete 'src/test/jastadd/relations/Relations2.ast', 'src/test/jastadd/relations/Relations2.jadd'
}
classpath = sourceSets.main.runtimeClasspath
main = 'org.jastadd.relast.compiler.Compiler'
//noinspection GroovyAssignabilityCheck
args 'src/test/jastadd/relations/Relations.ast', '--useJastAddNames', '--file', '--grammarName=src/test/jastadd/relations/Relations2'
}
task compileRelationTest(type: JavaExec, group: 'verification') {
doFirst {
delete 'src/test/java-gen/relations'
}
classpath = sourceSets.main.runtimeClasspath
main = 'org.jastadd.JastAdd'
//noinspection GroovyAssignabilityCheck
args '--o=src/test/java-gen/', '--package=relations.ast',
'src/test/jastadd/relations/Relations.ast',
'src/test/jastadd/relations/Relations.jadd',
'src/test/jastadd/Utils.jadd'
}
test.dependsOn compileRelationTest
compileRelationTest.dependsOn doublePreprocessRelationTest
doublePreprocessRelationTest.dependsOn preprocessRelationTest
task compileDefaultNamesTest(type: RelastTest) {
relastFiles 'src/test/jastadd/relations/Relations.relast'
grammarName = 'src/test/jastadd/relations/Relations3'
packageName = 'defaultnames.ast'
moreInputFiles 'src/test/jastadd/Utils.jadd'
}
task compileDefaultNamesResolverTest(type: RelastTest) {
relastFiles 'src/test/jastadd/resolver/Resolver.relast'
grammarName = 'src/test/jastadd/resolver/Resolver2'
resolverHelper = true
packageName = 'defaultnames.resolver.ast'
moreInputFiles 'src/test/jastadd/Utils.jadd',
'src/test/jastadd/resolver/ResolverUtils.jadd',
'src/test/jastadd/resolver/MyRefResolver.jadd'
}
task compileLowerBoundsTest(type: RelastTest) {
relastFiles 'src/test/jastadd/lowerbounds/LowerBounds.relast'
grammarName = 'src/test/jastadd/lowerbounds/LowerBounds'
useJastAddNames = true
packageName = 'lowerbounds.ast'
moreInputFiles 'src/test/jastadd/Utils.jadd'
}
task compileMultipleTest(type: RelastTest) {
relastFiles 'src/test/jastadd/multiple/Part1.relast',
'src/test/jastadd/multiple/Part2.relast',
'src/test/jastadd/multiple/Part3.relast'
grammarName = 'src/test/jastadd/multiple/Multiple'
useJastAddNames = true
packageName = 'multiple.ast'
moreInputFiles 'src/test/jastadd/Utils.jadd'
}
task compileResolverTest(type: RelastTest) {
relastFiles 'src/test/jastadd/resolver/Resolver.relast'
grammarName = 'src/test/jastadd/resolver/Resolver'
useJastAddNames = true
resolverHelper = true
packageName = 'resolver.ast'
moreInputFiles 'src/test/jastadd/Utils.jadd',
'src/test/jastadd/resolver/ResolverUtils.jadd',
'src/test/jastadd/resolver/MyRefResolver.jadd'
}
task compileResolver2Test(type: RelastTest) {
relastFiles 'src/test/jastadd/resolver2/Resolver.relast'
grammarName = 'src/test/jastadd/resolver2/Resolver'
useJastAddNames = true
resolverHelper = true
packageName = 'resolver2.ast'
moreInputFiles 'src/test/jastadd/Utils.jadd',
'src/test/jastadd/resolver2/ResolverUtils.jadd',
'src/test/jastadd/resolver2/MyRefResolver.jadd'
}
task compileListNamesTest(type: RelastTest) {
relastFiles 'src/test/jastadd/listnames/ListNames.relast'
grammarName = 'src/test/jastadd/listnames/ListNames'
useJastAddNames = true
jastAddList = 'ListyMcListface'
packageName = 'listnames.ast'
moreInputFiles 'src/test/jastadd/Utils.jadd'
}
task compileSerializerTest(type: RelastTest) {
relastFiles 'src/test/jastadd/serializer/Serializer.relast'
grammarName = 'src/test/jastadd/serializer/Serializer'
useJastAddNames = true
serializer = 'jackson'
packageName = 'serializer.ast'
moreInputFiles 'src/test/jastadd/Utils.jadd'
}
task compileSerializerDefaultNamesTest(type: RelastTest) {
relastFiles 'src/test/jastadd/serializer-names/Serializer.relast'
grammarName = 'src/test/jastadd/serializer-names/Serializer'
serializer = 'jackson'
packageName = 'defaultnames.serializer.ast'
moreInputFiles 'src/test/jastadd/Utils.jadd'
}
test {
outputs.upToDateWhen { false }
useJUnitPlatform()
}
<project name="RelAstCompiler" default="build" basedir=".">
<property name="srcdir" value="${basedir}/src" />
<property name="gendir" value="${srcdir}/generated" />
<property name="bindir" value="${basedir}/ant-bin" />
<property name="docdir" value="${basedir}/doc" />
<property name="tools" value="${basedir}/tools"/>
<property name="test-reports.dir" location="report-tests"/>
<property name="jarfile" value="relast-compiler.jar" />
<property name="junitjar" value="${tools}/junit-4.11-SNAPSHOT.jar" />
<!-- "package" is the directory where generated files will be stored -->
<property name="package" value="org.jastadd.relast.ast"/>
<loadresource property="package.path">
<propertyresource name="package"/>
<filterchain>
<tokenfilter>
<filetokenizer/>
<replacestring from="." to="/"/>
</tokenfilter>
</filterchain>
</loadresource>
<!-- Define Ant tasks -->
<taskdef name="jastadd" classname="org.jastadd.JastAddTask" classpath="${tools}/jastadd2.jar"/>
<taskdef name="jflex" classname="jflex.anttask.JFlexTask" classpath="${tools}/JFlex.jar"/>
<taskdef name="beaver" classname="beaver.comp.run.AntTask" classpath="${tools}/beaver.jar"/>
<!-- compile sources -->
<target name="build" depends="gen">
<mkdir dir="${bindir}" />
<javac
debug="true"
nowarn="true"
srcdir="${basedir}"
destdir="${bindir}"
includes="src/**/*.java"
classpath=".:${tools}/beaver-rt.jar:${junitjar}"
fork="true"
includeAntRuntime="false"
memoryMaximumSize="128M"
target="8"
source="8"
/>
</target>
<!-- generate compiler source files -->
<target name="gen" depends="scanner,parser">
<!-- create AST node types and weave aspect modules -->
<echo message = "Running JastAdd"/>
<jastadd package="${package}" rewrite="cnta" safeLazy="true" beaver="true" visitcheck="false"
lazyMaps="true" outdir="${gendir}" cache="all" lineColumnNumbers="true">
<fileset dir=".">
<include name="spec/jastadd/*.ast"/>
<include name="spec/jastadd/*.jadd"/>
<include name="spec/jastadd/*.jrag"/>
</fileset>
</jastadd>
</target>
<target name="scanner">
<jflex file="spec/scanner/RelAst.flex" outdir="${gendir}/${package.path}" InputStreamCtor="false" nobak="yes"/>
</target>
<target name="parser" depends="scanner">
<concat destfile="${gendir}/${package.path}/RelAstParser.all" binary="true" force="false">
<!-- we use filelist because the order is important -->
<filelist dir="spec/parser/">
<file name="Preamble.parser"/>
<file name="RelAstBase.parser"/>
</filelist>
</concat>
<!-- generate the parser phase 1, translating .parser to .beaver -->
<java classpath="${tools}/JastAddParser.jar:${tools}/beaver-rt.jar" classname="Main" fork="true">
<arg value="--no-beaver-symbol" />
<arg value="${gendir}/${package.path}/RelAstParser.all" />
<arg value="${gendir}/${package.path}/RelAstParser.beaver" />
</java>
<!-- generate the parser phase 2, translating .beaver to .java -->
<beaver file="${gendir}/${package.path}/RelAstParser.beaver" terminalNames="yes" compress="no" useSwitch="yes"/>
</target>
<!-- remove generated source files and .class files -->
<target name="clean">
<delete dir="${gendir}" />
<mkdir dir="${gendir}" />
<delete dir="${bindir}" />
<delete file="${jarfile}" />
<delete>
<fileset dir="." includes="**/*.class" excludes="bin/" />
</delete>
</target>
<target name="test" depends="build">
<mkdir dir="${test-reports.dir}"/>
<junit>
<classpath>
<pathelement path="${bindir}:${junitjar}:${tools}/beaver-rt.jar" />
</classpath>
<formatter type="brief" usefile="false" />
<batchtest todir="${test-reports.dir}">
<fileset dir="src/java">
<include name="org/jastadd/relast/tests/*.java" />
<include name="org/jastadd/relast/tests/codegen/*.java" />
</fileset>
</batchtest>
<formatter type="xml" />
</junit>
</target>
<target name="jar" depends="build">
<jar destfile="${jarfile}">
<fileset dir="${bindir}" includes="**/*.class" excludes="org/jastadd/relast/tests/*" />
<fileset dir="${srcdir}/java" includes="**/*.java" excludes="org/jastadd/relast/tests/*" />
<fileset dir="${gendir}" includes="**/*.java" />
<zipfileset includes="**/*.class" src="${tools}/beaver-rt.jar"/>
<manifest>
<attribute name="Main-Class" value="org.jastadd.relast.compiler.Compiler" />
</manifest>
</jar>
</target>
<target name="doc" depends="build" description="generate documentation">
<mkdir dir="${docdir}"/>
<javadoc
classpath="${gendir}:${tools}/beaver.jar"
destdir="${docdir}"
docletpath="${tools}/RagDoll.jar"
doclet="ragdoll.RagDollDoclet"
sourcepath="${gendir}">
<arg value="-linksource"/>
<arg value="-ragroot"/>
<arg value="."/>
</javadoc>
</target>
<!-- Run DrAST. Clone and build DrAST if it's not there -->
<target name="drast" depends="drast-init" >
<java jar="drast/DrAST-1.2.0.jar" fork="true" spawn="true" />
</target>
<target name="drast-init" depends="drast-check" unless="drast.exists" >
<exec executable="git">
<arg value="clone"/>
<arg value="git@bitbucket.org:jastadd/drast.git"/>
</exec>
<exec dir="drast" executable="./gradlew" />
</target>
<target name="drast-check">
<condition property="drast.exists">
<available file="drast" type="dir" />
</condition>
</target>
<target name="drast-update">
<delete dir="drast" />
<antcall target="drast-init" />
</target>
</project>
package org.jastadd.relast.plugin;
import org.gradle.api.Plugin;
import org.gradle.api.Project;
import org.gradle.api.Task;
import org.gradle.api.tasks.TaskCollection;
import java.util.Set;
/**
* Plugin for RelAst-Test.
*
* @author rschoene - Initial contribution
*/
public class RelastPlugin implements Plugin<Project> {
private Task testTask;
@Override
public void apply(Project project) {
Set<Task> tasks = project.getTasksByName("test", false);
// there should be only one task "test"
testTask = tasks.iterator().next();
TaskCollection<RelastTest> relastTests = project.getTasks().withType(RelastTest.class);
relastTests.forEach(this::setupRelastTest);
relastTests.whenTaskAdded(this::setupRelastTest);
}
private void setupRelastTest(RelastTest relastTest) {
testTask.dependsOn(relastTest);
relastTest.setGroup("verification");
}
}
package org.jastadd.relast.plugin;
import org.gradle.api.DefaultTask;
import org.gradle.api.Project;
import org.gradle.api.file.FileCollection;
import org.gradle.api.plugins.JavaPlugin;
import org.gradle.api.tasks.SourceSet;
import org.gradle.api.tasks.SourceSetContainer;
import org.gradle.api.tasks.TaskAction;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* RelAst Test Task
*
* @author rschoene - Initial contribution
*/
@SuppressWarnings({"unused", "WeakerAccess"})
public class RelastTest extends DefaultTask {
// general options
private boolean verbose = false;
// pre-process options
private List<String> relastFiles = new ArrayList<>();
private boolean useJastAddNames;
private boolean resolverHelper;
private boolean writeToFile = true;
private String grammarName;
private String listClass;
private String jastAddList;
private String serializer;
// compile options
private boolean runJastAdd = true;
private String outputDir = "src/test/java-gen/";
private String packageName;
private List<String> moreInputFiles = new ArrayList<>();
public boolean isVerbose() {
return verbose;
}
public void setVerbose(boolean verbose) {
this.verbose = verbose;
}
// pre-process options
public List<String> getRelastFiles() {
return relastFiles;
}
public void relastFiles(String relastFile) {
this.relastFiles.add(relastFile);
}
public void relastFiles(String[] relastFilesArray) {
this.relastFiles = Arrays.asList(relastFilesArray);
}
public boolean isUseJastAddNames() {
return useJastAddNames;
}
public void setUseJastAddNames(boolean useJastAddNames) {
this.useJastAddNames = useJastAddNames;
}
public boolean isResolverHelper() {
return resolverHelper;
}
public void setResolverHelper(boolean resolverHelper) {
this.resolverHelper = resolverHelper;
}
public boolean isWriteToFile() {
return writeToFile;
}
public void setWriteToFile(boolean writeToFile) {
this.writeToFile = writeToFile;
}
public String getGrammarName() {
return grammarName;
}
public void setGrammarName(String grammarName) {
this.grammarName = grammarName;
}
public String getListClass() {
return listClass;
}
public void setListClass(String listClass) {
this.listClass = listClass;
}
public String getJastAddList() {
return jastAddList;
}
public void setJastAddList(String jastAddList) {
this.jastAddList = jastAddList;
}
public String getSerializer() {
return serializer;
}
public void setSerializer(String serializer) {
this.serializer = serializer;
}
// compile options
public boolean isRunJastAdd() {
return runJastAdd;
}
public void setRunJastAdd(boolean runJastAdd) {
this.runJastAdd = runJastAdd;
}
public String getOutputDir() {
return outputDir;
}
public void setOutputDir(String outputDir) {
this.outputDir = outputDir;
}
public String getPackageName() {
return packageName;
}
public void setPackageName(String packageName) {
this.packageName = packageName;
}
public List<String> getMoreInputFiles() {
return moreInputFiles;
}
public void moreInputFiles(String f) {
this.moreInputFiles.add(f);
}
public void moreInputFiles(String[] fileArray) {
this.moreInputFiles.addAll(Arrays.asList(fileArray));
}
private boolean isSet(String option) {
return option != null && !option.isEmpty();
}
private String[] genSuffixes = {".ast", ".jadd", "RefResolver.jadd", "ResolverStubs.jrag", "Serializer.jadd"};
@TaskAction
void runTest() {
setGroup("verification");
setDescription("Runs a relast test");
Project project = getProject();
if (isVerbose()) {
System.out.println("Running relast test");
System.out.println("relast files: " + getRelastFiles());
System.out.println("Deleting files");
}
// first, delete generated files
List<String> genFiles = new ArrayList<>();
for (String suffix : genSuffixes) {
genFiles.add(getGrammarName() + suffix);
}
if (isVerbose()) {
System.out.println("gen files: " + genFiles);
}
project.delete(deleteSpec -> {
deleteSpec.delete(genFiles);
if (isSet(getPackageName())) {
deleteSpec.delete(Paths.get(getOutputDir(), getPackageName()));
}
});
if (isVerbose()) {
System.out.println("Pre processing, running relast");
}
// then, run relast pre processing
project.getPlugins().withType(JavaPlugin.class, javaPlugin -> {
SourceSetContainer sourceSets = (SourceSetContainer) project.getProperties().get("sourceSets");
FileCollection runtimeClasspath = sourceSets.getByName(SourceSet.MAIN_SOURCE_SET_NAME).getRuntimeClasspath();
project.javaexec(javaExecSpec -> {
javaExecSpec.setClasspath(runtimeClasspath);
javaExecSpec.setMain("org.jastadd.relast.compiler.Compiler");
List<Object> args = new ArrayList<>(getRelastFiles());
if (isWriteToFile()) {
args.add("--file");
}
if (isUseJastAddNames()) {
args.add("--useJastAddNames");
}
if (isResolverHelper()) {
args.add("--resolverHelper");
}
if (isSet(getJastAddList())) {
args.add("--jastAddList=" + getJastAddList());
}
if (isSet(getListClass())) {
args.add("--listClass=" + getListClass());
}
if (isSet(getSerializer())) {
args.add("--serializer=" + getSerializer());
}
args.add("--grammarName=" + getGrammarName());
if (isVerbose()) {
System.out.println("Start relast with args: " + args);
}
javaExecSpec.args(args);
});
});
if (isRunJastAdd()) {
if (isVerbose()) {
System.out.println("Compile with JastAdd");
}
// check which files were actually generated
genFiles.removeIf(s -> !Paths.get(s).toFile().exists());
// finally, compile generated files
project.getPlugins().withType(JavaPlugin.class, javaPlugin -> {
SourceSetContainer sourceSets = (SourceSetContainer) project.getProperties().get("sourceSets");
FileCollection runtimeClasspath = sourceSets.getByName(SourceSet.MAIN_SOURCE_SET_NAME).getRuntimeClasspath();
project.javaexec(javaExecSpec -> {
javaExecSpec.setClasspath(runtimeClasspath);
javaExecSpec.setMain("org.jastadd.JastAdd");
List<Object> args = new ArrayList<>();
args.add("--o=" + getOutputDir());
args.add("--package=" + getPackageName());
if (isSet(getJastAddList())) {
args.add("--List=" + getJastAddList());
}
args.addAll(genFiles);
args.addAll(getMoreInputFiles());
if (isVerbose()) {
System.out.println("Start JastAdd with args: " + args);
}
javaExecSpec.args(args);
});
});
}
}
}
implementation-class=org.jastadd.relast.plugin.RelastPlugin
File added
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.3-bin.zip
gradlew 0 → 100755
#!/usr/bin/env sh
##############################################################################
##
## Gradle start up script for UN*X
##
##############################################################################
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`"/$link"
fi
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >/dev/null
APP_HOME="`pwd -P`"
cd "$SAVED" >/dev/null
APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS=""
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
warn () {
echo "$*"
}
die () {
echo
echo "$*"
echo
exit 1
}
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
nonstop=false
case "`uname`" in
CYGWIN* )
cygwin=true
;;
Darwin* )
darwin=true
;;
MINGW* )
msys=true
;;
NONSTOP* )
nonstop=true
;;
esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
else
JAVACMD="$JAVA_HOME/bin/java"
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD="java"
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
MAX_FD_LIMIT=`ulimit -H -n`
if [ $? -eq 0 ] ; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
MAX_FD="$MAX_FD_LIMIT"
fi
ulimit -n $MAX_FD
if [ $? -ne 0 ] ; then
warn "Could not set maximum file descriptor limit: $MAX_FD"
fi
else
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
fi
fi
# For Darwin, add options to specify how the application appears in the dock
if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi
# For Cygwin, switch paths to Windows format before running java
if $cygwin ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
JAVACMD=`cygpath --unix "$JAVACMD"`
# We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
SEP=""
for dir in $ROOTDIRSRAW ; do
ROOTDIRS="$ROOTDIRS$SEP$dir"
SEP="|"
done
OURCYGPATTERN="(^($ROOTDIRS))"
# Add a user-defined pattern to the cygpath arguments
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
fi
# Now convert the arguments - kludge to limit ourselves to /bin/sh
i=0
for arg in "$@" ; do
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
else
eval `echo args$i`="\"$arg\""
fi
i=$((i+1))
done
case $i in
(0) set -- ;;
(1) set -- "$args0" ;;
(2) set -- "$args0" "$args1" ;;
(3) set -- "$args0" "$args1" "$args2" ;;
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
esac
fi
# Escape application args
save () {
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
echo " "
}
APP_ARGS=$(save "$@")
# Collect all arguments for the java command, following the shell quoting and substitution rules
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
cd "$(dirname "$0")"
fi
exec "$JAVACMD" "$@"
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS=
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto init
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto init
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:init
@rem Get command-line arguments, handling Windows variants
if not "%OS%" == "Windows_NT" goto win9xME_args
:win9xME_args
@rem Slurp the command line arguments.
set CMD_LINE_ARGS=
set _SKIP=2
:win9xME_args_slurp
if "x%~1" == "x" goto execute
set CMD_LINE_ARGS=%*
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega
import java.util.*;
aspect TypeAnalysis {
public abstract TypeUse Component.getTypeUse();
syn TypeDecl TypeUse.decl() = lookupType(getID());
inh TypeDecl TypeUse.lookupType(String name);
eq Program.getChild().lookupType(String name) {
for (TypeDecl td: getTypeDecls()) {
if (td.getID().equals(name)) {
return td;
}
}
return null;
}
syn boolean TypeDecl.isAlreadyDeclared()
= lookupType(getID()) != this;
inh TypeDecl TypeDecl.lookupType(String name);
}
aspect ComponentAnalysis {
syn boolean Component.isTargetOfDirectedRelation() = false;
eq RelationComponent.isTargetOfDirectedRelation() = isTargetOfRightDirection();
inh boolean RelationComponent.isTargetOfRightDirection();
eq Relation.getRight().isTargetOfRightDirection()
= getDirection() instanceof RightDirection;
eq Program.getChild().isTargetOfRightDirection() = false;
syn String Component.name() = getID();
syn TypeDecl Component.toTypeDecl() = enclosingTypeDecl();
eq RelationComponent.toTypeDecl() = getTypeUse().decl();
inh TypeDecl Component.enclosingTypeDecl();
eq TypeDecl.getChild().enclosingTypeDecl() = this;
eq Program.getChild().enclosingTypeDecl() = null;
inh RelationComponent RelationComponent.otherSide();
eq Relation.getLeft().otherSide() = getRight();
eq Relation.getRight().otherSide() = getLeft();
eq Program.getChild().otherSide() = null;
syn TypeDecl RelationComponent.ofTypeDecl() = otherSide().toTypeDecl();
syn boolean Component.isAlreadyDeclared()
= !isTargetOfDirectedRelation()
&& toTypeDecl() != null
&& lookupComponent(toTypeDecl(), name()) != this;
inh Component Component.lookupComponent(TypeDecl td, String name);
eq Program.getChild().lookupComponent(TypeDecl td, String name)
= lookupComponentSyn(td, name);
syn Component Program.lookupComponentSyn(TypeDecl td, String name) {
// Check super type first to find duplicates (shadowing is not allowed)
if (td.hasSuper() && td.getSuper().decl() != null) {
Component c = lookupComponentSyn(td.getSuper().decl(), name);
if (c != null) return c;
}
for (Component c: td.getComponents()) {
if (c.name().equals(name)) {
return c;
}
}
for (Relation r: getRelations()) {
Component c = r.getLeft().lookup(td, name);
if (c != null) return c;
c = r.getRight().lookup(td, name);
if (c != null) return c;
}
return null;
}
syn RelationComponent RelationComponent.lookup(TypeDecl td, String name)
= !isTargetOfDirectedRelation() && toTypeDecl() == td && name().equals(name)
? this
: null;
coll Set<RelationComponent> TypeDecl.relationComponents()
[new HashSet<RelationComponent>()]
root Program;
RelationComponent contributes this
when !isTargetOfDirectedRelation() && toTypeDecl() != null
to TypeDecl.relationComponents()
for toTypeDecl();
syn Set<OneRelationComponent> TypeDecl.oneRelationComponents() {
Set<OneRelationComponent> set = new HashSet<>();
for (RelationComponent rc: relationComponents()) {
if (rc instanceof OneRelationComponent) {
set.add((OneRelationComponent) rc);
}
}
return set;
}
}
aspect Constructors {
syn Collection<Component> TypeDecl.componentsTransitive() {
ArrayList<Component> list = new ArrayList<>();
if (hasSuper() && getSuper().decl() != null) {
list.addAll(getSuper().decl().componentsTransitive());
}
for (Component c: getComponents()) {
list.add(c);
}
return list;
}
syn boolean TypeDecl.needsConstructor() {
if (componentsTransitive().isEmpty()) {
return false;
}
if (!relationComponents().isEmpty()) {
return true;
}
return hasSuper()
&& getSuper().decl() != null
&& getSuper().decl().needsConstructor();
}
}
aspect Utils {
public String SimpleTypeUse.toString() {
return getID();
}
public String ParameterizedTypeUse.toString() {
StringBuilder sb = new StringBuilder();
sb.append(getID()).append("<");
int i = 0;
for (TypeUse u: getTypeUses()) {
sb.append(u.toString());
if (++i < getNumTypeUse()) {
sb.append(", ");
}
}
sb.append(">");
return sb.toString();
}
public String TypeDecl.toString() {
return getID();
}
}
aspect BackendAbstractGrammar {
public static String ASTNode.listClass = "ArrayList";
public String Program.generateAbstractGrammar() {
StringBuilder sb = new StringBuilder();
generateAbstractGrammar(sb);
return sb.toString();
}
public void Program.generateAbstractGrammar(StringBuilder sb) {
for (TypeDecl td: getTypeDecls()) {
td.generateAbstractGrammar(sb);
}
}
public void TypeDecl.generateAbstractGrammar(StringBuilder sb) {
if (getAbstract()) {
sb.append("abstract ");
}
sb.append(getID());
if (hasSuper()) {
sb.append(" : " + getSuper());
}
if (getNumComponent() > 0 || relationComponents().size() > 0) {
sb.append(" ::=");
}
for (Component c: getComponents()) {
sb.append(" ");
sb.append(c.generateAbstractGrammar());
}
for (RelationComponent c: relationComponents()) {
sb.append(" ");
sb.append(c.generateAbstractGrammar());
}
sb.append(";\n");
}
public String Component.generateAbstractGrammar() {
if (getID().equals(getTypeUse().toString())) {
return getTypeUse().toString();
} else {
return getID() + ":" + getTypeUse();
}
}
public String ListComponent.generateAbstractGrammar() {
return super.generateAbstractGrammar() + "*";
}
public String OptComponent.generateAbstractGrammar() {
return "[" + super.generateAbstractGrammar() + "]";
}
public String NTAComponent.generateAbstractGrammar() {
return "/" + super.generateAbstractGrammar() + "/";
}
public String TokenComponent.generateAbstractGrammar() {
return "<" + getID() + ":" + getTypeUse() + ">";
}
public String RelationComponent.generateAbstractGrammar() {
return "<" + getImplAttributeName() + ":" + ofTypeDecl() + ">";
}
public String ManyRelationComponent.generateAbstractGrammar() {
return "<" + getImplAttributeName() + ":" + ASTNode.listClass + "<" + ofTypeDecl() + ">>";
}
public String RelationComponent.getImplAttributeName() {
return "_impl_" + getID();
}
}
aspect BackendAspect {
public String Program.generateAspect() {
StringBuilder sb = new StringBuilder();
generateAspect(sb);
return sb.toString();
}
public void Program.generateAspect(StringBuilder sb) {
sb.append("import java.util.ArrayList;\n");
sb.append("import java.util.Collections;\n");
sb.append("aspect RelAstAPI {\n");
for (TypeDecl td: getTypeDecls()) {
if (td.needsConstructor()) {
td.generateConstructor(sb);
}
}
for (Relation r: getRelations()) {
r.generateAPI(sb);
}
generateLowerBoundCheck(sb);
sb.append(ind(1) + "public static void ASTNode.assertNotNull(Object obj) {\n");
sb.append(ind(2) + "if (obj == null) {\n");
sb.append(ind(3) + "throw new NullPointerException();\n");
sb.append(ind(2) + "}\n");
sb.append(ind(1) + "}\n");
sb.append("}\n");
}
public void TypeDecl.generateConstructor(StringBuilder sb) {
sb.append(ind(1) + "public " + getID() + "." + getID() + "(");
int i = 0;
for (Component c: componentsTransitive()) {
sb.append(c.constructorParameter());
if (++i < componentsTransitive().size()) {
sb.append(", ");
}
}
sb.append(") {\n");
for (Component c: componentsTransitive()) {
sb.append(ind(2) + c.constructorSetMethod() + "(" + c.getID() + ");\n");
}
sb.append(ind(1) + "}\n");
}
public String Component.constructorParameter() {
return getTypeUse() + " " + getID();
}
public String ListComponent.constructorParameter() {
return "List<" + getTypeUse() + "> " + getID();
}
public String OptComponent.constructorParameter() {
return "Opt<" + getTypeUse() + "> " + getID();
}
public String Component.constructorSetMethod() {
return "set" + getID();
}
public String ListComponent.constructorSetMethod() {
return "set" + getID() + "List";
}
public String OptComponent.constructorSetMethod() {
return "set" + getID() + "Opt";
}
}
aspect BackendAPI {
public void Relation.generateAPI(StringBuilder sb) {
sb.append(ind(1) + "// " + prettyPrint() + "\n");
getDirection().generateAPI(sb);
sb.append("\n");
}
public abstract void Direction.generateAPI(StringBuilder sb);
inh Relation Direction.relation();
eq Relation.getChild().relation() = this;
eq Program.getChild().relation() = null;
public String RelationComponent.nameCapitalized() {
return name().substring(0,1).toUpperCase() + name().substring(1);
}
}
aspect BackendDirectedAPI {
public void RightDirection.generateAPI(StringBuilder sb) {
relation().getLeft().generateDirectedAPI(sb);
}
public abstract void RelationComponent.generateDirectedAPI(StringBuilder sb);
public void OneRelationComponent.generateDirectedAPI(StringBuilder sb) {
generateDirectedZeroOneAPI(sb, false);
}
public void OptionalRelationComponent.generateDirectedAPI(StringBuilder sb) {
generateDirectedZeroOneAPI(sb, true);
generateExtraOptAPI(sb);
}
public void RelationComponent.generateDirectedZeroOneAPI(StringBuilder sb, boolean optional) {
// Get
generateGetOne(sb);
// Set
sb.append(ind(1) + "public void " + toTypeDecl());
sb.append(".set" + nameCapitalized() + "(" + ofTypeDecl() + " o) {\n");
if (!optional) {
sb.append(ind(2) + "assertNotNull(o);\n");
}
sb.append(ind(2) + "set" + getImplAttributeName() + "(o);\n");
sb.append(ind(1) + "}\n");
}
public void ManyRelationComponent.generateDirectedAPI(StringBuilder sb) {
// Get
generateGetMany(sb);
// Add
sb.append(ind(1) + "public void " + toTypeDecl() + ".addTo");
sb.append(nameCapitalized() + "(" + ofTypeDecl() + " o) {\n");
sb.append(ind(2) + "assertNotNull(o);\n");
sb.append(ind(2) + ASTNode.listClass + "<" + ofTypeDecl() + "> list = get" + getImplAttributeName() + "();\n");
sb.append(ind(2) + "if (list == null) {\n");
sb.append(ind(3) + "list = new " + ASTNode.listClass + "<>();\n");
sb.append(ind(2) + "}\n");
sb.append(ind(2) + "list.add(o);\n");
sb.append(ind(2) + "set" + getImplAttributeName() + "(list);\n");
sb.append(ind(1) + "}\n");
// Remove
sb.append(ind(1) + "public void " + toTypeDecl() + ".removeFrom");
sb.append(nameCapitalized() + "(" + ofTypeDecl() + " o) {\n");
sb.append(ind(2) + "assertNotNull(o);\n");
sb.append(ind(2) + ASTNode.listClass + "<" + ofTypeDecl() + "> list = get" + getImplAttributeName() + "();\n");
sb.append(ind(2) + "if (list != null && list.remove(o)) {\n");
sb.append(ind(3) + "set" + getImplAttributeName() + "(list);\n");
sb.append(ind(2) + "}\n");
sb.append(ind(1) + "}\n");
}
public void RelationComponent.generateGetOne(StringBuilder sb) {
sb.append(ind(1) + "public " + ofTypeDecl() + " " + toTypeDecl());
sb.append("." + name() + "() {\n");
sb.append(ind(2) + "return get" + getImplAttributeName() + "();\n");
sb.append(ind(1) + "}\n");
}
public void RelationComponent.generateExtraOptAPI(StringBuilder sb) {
// has
sb.append(ind(1) + "public boolean " + toTypeDecl());
sb.append(".has" + nameCapitalized() + "() {\n");
sb.append(ind(2) + "return " + name() + "() != null;\n");
sb.append(ind(1) + "}\n");
// clear
sb.append(ind(1) + "public void " + toTypeDecl());
sb.append(".clear" + nameCapitalized() + "() {\n");
sb.append(ind(2) + "set" + nameCapitalized() + "(null);\n");
sb.append(ind(1) + "}\n");
}
public void RelationComponent.generateGetMany(StringBuilder sb) {
sb.append(ind(1) + "public java.util.List<" + ofTypeDecl() + "> " + toTypeDecl());
sb.append("." + name() + "() {\n");
sb.append(ind(2) + ASTNode.listClass + "<" + ofTypeDecl() + "> l = get"
+ getImplAttributeName() + "();\n");
sb.append(ind(2) + "return l != null ? Collections.unmodifiableList(l) : Collections.emptyList();\n");
sb.append(ind(1) + "}\n");
}
}
aspect BackendBidirectionalAPI {
public void Bidirectional.generateAPI(StringBuilder sb) {
RelationComponent l = relation().getLeft();
RelationComponent r = relation().getRight();
if (l.multiplicityOne()) {
if (r.multiplicityOne()) {
l.generateBiOneOne(sb, false);
r.generateBiOneOne(sb, false);
} else if (r.multiplicityOpt()) {
l.generateBiOneOne(sb, false);
r.generateBiOneOne(sb, true);
} else if (r.multiplicityMany()) {
l.generateBiOneMany(sb, false);
r.generateBiManyOne(sb);
}
} else if (l.multiplicityOpt()) {
if (r.multiplicityOne()) {
l.generateBiOneOne(sb, true);
r.generateBiOneOne(sb, false);
} else if (r.multiplicityOpt()) {
l.generateBiOneOne(sb, true);
r.generateBiOneOne(sb, true);
} else if (r.multiplicityMany()) {
l.generateBiOneMany(sb, true);
r.generateBiManyOne(sb);
}
} else if (l.multiplicityMany()) {
if (r.multiplicityOne()) {
l.generateBiManyOne(sb);
r.generateBiOneMany(sb, false);
} else if (r.multiplicityOpt()) {
l.generateBiManyOne(sb);
r.generateBiOneMany(sb, true);
} else if (r.multiplicityMany()) {
l.generateBiManyMany(sb);
r.generateBiManyMany(sb);
}
}
}
public void RelationComponent.generateBiOneOne(StringBuilder sb, boolean isOpt) {
// Get
generateGetOne(sb);
// Set
sb.append(ind(1) + "public void " + toTypeDecl());
sb.append(".set" + nameCapitalized() + "(" + ofTypeDecl() + " o) {\n");
if (!isOpt) {
sb.append(ind(2) + "assertNotNull(o);\n");
}
sb.append(ind(2) + "if (get" + getImplAttributeName() + "() != null) {\n");
sb.append(ind(3) + "get" + getImplAttributeName() + "().set" + otherSide().getImplAttributeName() + "(null);\n");
sb.append(ind(2) + "}\n");
sb.append(ind(2) + "if (o != null && o.get" + otherSide().getImplAttributeName() + "() != null) {\n");
sb.append(ind(3) + "o.get" + otherSide().getImplAttributeName() + "().set" + getImplAttributeName() + "(null);\n");
sb.append(ind(2) + "}\n");
sb.append(ind(2) + "set" + getImplAttributeName() + "(o);\n");
if (isOpt) {
sb.append(ind(2) + "if (o != null) {\n");
sb.append(ind(3) + "o.set" + otherSide().getImplAttributeName() + "(this);\n");
sb.append(ind(2) + "}\n");
} else {
sb.append(ind(2) + "o.set" + otherSide().getImplAttributeName() + "(this);\n");
}
sb.append(ind(1) + "}\n");
if (isOpt) {
generateExtraOptAPI(sb);
}
}
public void RelationComponent.generateBiManyMany(StringBuilder sb) {
// Get
generateGetMany(sb);
// Add
sb.append(ind(1) + "public void " + toTypeDecl() + ".addTo");
sb.append(nameCapitalized() + "(" + ofTypeDecl() + " o) {\n");
sb.append(ind(2) + "assertNotNull(o);\n");
sb.append(ind(2) + ASTNode.listClass + "<" + ofTypeDecl() + "> list = get" + getImplAttributeName() + "();\n");
sb.append(ind(2) + "if (list == null) {\n");
sb.append(ind(3) + "list = new " + ASTNode.listClass + "<>();\n");
sb.append(ind(2) + "}\n");
sb.append(ind(2) + ASTNode.listClass + "<" + otherSide().ofTypeDecl() + "> list2 = o.get"
+ otherSide().getImplAttributeName() + "();\n");
sb.append(ind(2) + "if (list2 == null) {\n");
sb.append(ind(3) + "list2 = new "+ ASTNode.listClass + "<>();\n");
sb.append(ind(2) + "}\n");
sb.append(ind(2) + "list.add(o);\n");
sb.append(ind(2) + "list2.add(this);\n");
sb.append(ind(2) + "set" + getImplAttributeName() + "(list);\n");
sb.append(ind(2) + "o.set" + otherSide().getImplAttributeName() + "(list2);\n");
sb.append(ind(1) + "}\n");
// Remove
sb.append(ind(1) + "public void " + toTypeDecl() + ".removeFrom");
sb.append(nameCapitalized() + "(" + ofTypeDecl() + " o) {\n");
sb.append(ind(2) + "assertNotNull(o);\n");
sb.append(ind(2) + ASTNode.listClass + "<" + ofTypeDecl() + "> list = get" + getImplAttributeName() + "();\n");
sb.append(ind(2) + "if (list != null && list.remove(o)) {\n");
sb.append(ind(3) + ASTNode.listClass + "<" + otherSide().ofTypeDecl() + "> list2 = o.get"
+ otherSide().getImplAttributeName() + "();\n");
sb.append(ind(3) + "if (list2 != null) list2.remove(this);\n");
sb.append(ind(3) + "set" + getImplAttributeName() + "(list);\n");
sb.append(ind(3) + "o.set" + otherSide().getImplAttributeName() + "(list2);\n");
sb.append(ind(2) + "}\n");
sb.append(ind(1) + "}\n");
}
public void RelationComponent.generateBiManyOne(StringBuilder sb) {
// Get
generateGetMany(sb);
// Add
sb.append(ind(1) + "public void " + toTypeDecl() + ".addTo");
sb.append(nameCapitalized() + "(" + ofTypeDecl() + " o) {\n");
sb.append(ind(2) + "assertNotNull(o);\n");
sb.append(ind(2) + "if (o != null && o.get" + otherSide().getImplAttributeName() + "() != null) {\n");
sb.append(ind(3) + ASTNode.listClass + "<" + ofTypeDecl() + "> list2 = o.get"
+ otherSide().getImplAttributeName() + "().get" + getImplAttributeName() + "();\n");
sb.append(ind(3) + "if (list2.remove(o))\n");
sb.append(ind(4) + "o.get" + otherSide().getImplAttributeName()
+ "().set" + getImplAttributeName() + "(list2);\n");
sb.append(ind(2) + "}\n");
sb.append(ind(2) + ASTNode.listClass + "<" + ofTypeDecl() + "> list = get" + getImplAttributeName() + "();\n");
sb.append(ind(2) + "if (list == null) {\n");
sb.append(ind(3) + "list = new " + ASTNode.listClass + "<>();\n");
sb.append(ind(2) + "}\n");
sb.append(ind(2) + "list.add(o);\n");
sb.append(ind(2) + "set" + getImplAttributeName() + "(list);\n");
sb.append(ind(2) + "o.set" + otherSide().getImplAttributeName() + "(this);\n");
sb.append(ind(1) + "}\n");
// Remove
sb.append(ind(1) + "public void " + toTypeDecl() + ".removeFrom");
sb.append(nameCapitalized() + "(" + ofTypeDecl() + " o) {\n");
sb.append(ind(2) + "assertNotNull(o);\n");
sb.append(ind(2) + ASTNode.listClass + "<" + ofTypeDecl() + "> list = get" + getImplAttributeName() + "();\n");
sb.append(ind(2) + "if (list != null && list.remove(o)) {\n");
sb.append(ind(3) + "set" + getImplAttributeName() + "(list);\n");
sb.append(ind(3) + "if (o.get" + otherSide().getImplAttributeName() + "() == this) {\n");
sb.append(ind(4) + "o.set" + otherSide().getImplAttributeName() + "(null);\n");
sb.append(ind(3) + "}\n");
sb.append(ind(2) + "}\n");
sb.append(ind(1) + "}\n");
}
public void RelationComponent.generateBiOneMany(StringBuilder sb, boolean isOpt) {
// Get
generateGetOne(sb);
// Set
sb.append(ind(1) + "public void " + toTypeDecl() + ".set" + nameCapitalized()
+ "(" + ofTypeDecl() + " o) {\n");
if (!isOpt) {
sb.append(ind(2) + "assertNotNull(o);\n");
}
sb.append(ind(2) + "if (get" + getImplAttributeName() + "() != null) {\n");
sb.append(ind(3) + ASTNode.listClass + "<" + toTypeDecl() + "> list2 = get" + getImplAttributeName()
+ "()." + "get" + otherSide().getImplAttributeName() + "();\n");
sb.append(ind(3) + "list2.remove(this);\n");
sb.append(ind(3) + "get" + getImplAttributeName() + "()." + "set"
+ otherSide().getImplAttributeName() + "(list2);\n");
sb.append(ind(2) + "}\n");
sb.append(ind(2) + "set" + getImplAttributeName() + "(o);\n");
int ind = isOpt ? 3 : 2;
if (isOpt) {
sb.append(ind(2) + "if (o != null) {\n");
}
sb.append(ind(ind) + ASTNode.listClass + "<" + toTypeDecl() + "> list = o.get"
+ otherSide().getImplAttributeName() + "();\n");
sb.append(ind(ind) + "if (list == null) {\n");
sb.append(ind(ind+1) + "list = new " + ASTNode.listClass + "<>();\n");
sb.append(ind(ind) + "}\n");
sb.append(ind(ind) + "list.add(this);\n");
sb.append(ind(ind) + "o.set" + otherSide().getImplAttributeName() + "(list);\n");
if (isOpt) {
sb.append(ind(2) + "}\n");
}
sb.append(ind(1) + "}\n");
if (isOpt) {
generateExtraOptAPI(sb);
}
}
}
aspect LowerBoundCheck {
public void Program.generateLowerBoundCheck(StringBuilder sb) {
sb.append(ind(1) + "public boolean ASTNode.violatesLowerBounds() {\n");
sb.append(ind(2) + "return !getLowerBoundsViolations().isEmpty();\n");
sb.append(ind(1) + "}\n");
sb.append(ind(1) + "public java.util.List<Pair<ASTNode, String>> "
+ "ASTNode.getLowerBoundsViolations() {\n");
sb.append(ind(2) + "ArrayList<Pair<ASTNode, String>> list = new ArrayList<>();\n");
sb.append(ind(2) + "computeLowerBoundsViolations(list);\n");
sb.append(ind(2) + "return list;\n");
sb.append(ind(1) + "}\n");
sb.append(ind(1) + "public void ASTNode.computeLowerBoundsViolations("
+ "java.util.List<Pair<ASTNode, String>> list) {\n");
sb.append(ind(2) + "for (int i = 0; i < getNumChildNoTransform(); i++) {\n");
sb.append(ind(3) + "getChildNoTransform(i).computeLowerBoundsViolations(list);\n");
sb.append(ind(2) + "}\n");
sb.append(ind(1) + "}\n");
for (TypeDecl td: getTypeDecls()) {
td.generateLowerBoundCheck(sb);
}
generatePairClass(sb);
}
public void TypeDecl.generateLowerBoundCheck(StringBuilder sb) {
if (!oneRelationComponents().isEmpty()) {
sb.append(ind(1) + "public void " + getID() + ".computeLowerBoundsViolations(" +
"java.util.List<Pair<ASTNode, String>> list) {\n");
for (OneRelationComponent o: oneRelationComponents()) {
o.generateLowerBoundCheck(sb);
}
sb.append(ind(2) + "super.computeLowerBoundsViolations(list);\n");
sb.append(ind(1) + "}\n");
}
}
public void OneRelationComponent.generateLowerBoundCheck(StringBuilder sb) {
sb.append(ind(2) + "if (" + name() + "() == null) {\n");
sb.append(ind(3) + "list.add(new Pair<>(this, \"" + name() + "\"));\n");
sb.append(ind(2) + "}\n");
}
public void Program.generatePairClass(StringBuilder sb) {
sb.append(ind(1) + "public class Pair<T1, T2> {\n");
sb.append(ind(2) + "public final T1 _1;\n");
sb.append(ind(2) + "public final T2 _2;\n");
// Constructor
sb.append(ind(2) + "public Pair(T1 _1, T2 _2) {\n");
sb.append(ind(3) + "ASTNode.assertNotNull(_1);\n");
sb.append(ind(3) + "ASTNode.assertNotNull(_2);\n");
sb.append(ind(3) + "this._1 = _1;\n");
sb.append(ind(3) + "this._2 = _2;\n");
sb.append(ind(2) + "}\n");
// equals
sb.append(ind(2) + "public boolean equals(Object other) {\n");
sb.append(ind(3) + "if (other instanceof Pair) {\n");
sb.append(ind(4) + "Pair<?,?> p = (Pair<?,?>) other;\n");
sb.append(ind(4) + "return _1.equals(p._1) && _2.equals(p._2);\n");
sb.append(ind(3) + "} else {\n");
sb.append(ind(4) + "return false;\n");
sb.append(ind(3) + "}\n");
sb.append(ind(2) + "}\n");
// hashCode
sb.append(ind(2) + "public int hashCode() {\n");
sb.append(ind(3) + "return 31*_1.hashCode() + _2.hashCode();\n");
sb.append(ind(2) + "}\n");
sb.append(ind(1) + "}\n");
}
}
aspect PrettyPrint {
public String Relation.prettyPrint() {
return "rel "
+ getLeft().prettyPrint() + " "
+ getDirection().prettyPrint() + " "
+ getRight().prettyPrint();
}
public String RelationComponent.prettyPrint() {
if (getID().isEmpty()) {
return getTypeUse().toString();
} else {
return getTypeUse() + "." + getID();
}
}
public String OptionalRelationComponent.prettyPrint() {
return super.prettyPrint() + "?";
}
public String ManyRelationComponent.prettyPrint() {
return super.prettyPrint() + "*";
}
abstract public String Direction.prettyPrint();
public String RightDirection.prettyPrint() {
return "->";
}
public String Bidirectional.prettyPrint() {
return "<->";
}
}
aspect Utils {
public String ASTNode.ind(int n) {
String s = "";
for (int i = 0; i < n; i++) {
s += " ";
}
return s;
}
}
\ No newline at end of file
import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
import java.lang.reflect.InvocationTargetException;
// We have been careful to not import many types here because the imports are added for
// _ALL_ AST nodes and can cause collisions in the abstract grammar namespace.
aspect DumpTree {
private static final String ASTNode.DUMP_TREE_INDENT = " ";
public String ASTNode.dumpTree() {
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
dumpTree(new PrintStream(bytes));
return bytes.toString();
}
public void ASTNode.dumpTree(PrintStream out) {
dumpTree(out, "");
out.flush();
}
public void ASTNode.dumpTree(PrintStream out, String indent) {
out.print(indent + getClass().getSimpleName());
out.print(getTokens());
String extra = extraDumpInfo();
if (!extra.isEmpty()) {
out.print(" " + extra);
}
out.println();
String childIndent = indent + DUMP_TREE_INDENT;
for (ASTNode child : astChildren()) {
if (child == null) {
out.println(childIndent + "null");
} else {
child.dumpTree(out, childIndent);
}
}
}
public String ASTNode.extraDumpInfo() { return ""; }
public String ASTNode.getTokens() {
java.util.TreeSet<java.lang.reflect.Method> methods = new java.util.TreeSet<>(
new java.util.Comparator<java.lang.reflect.Method>() {
public int compare(java.lang.reflect.Method m1, java.lang.reflect.Method m2) {
return m1.getName().compareTo(m2.getName());
}
});
methods.addAll(java.util.Arrays.asList(getClass().getMethods()));
String result = "";
for (java.lang.reflect.Method method : methods) {
ASTNodeAnnotation.Token token = method.getAnnotation(ASTNodeAnnotation.Token.class);
if (token != null) {
try {
result += String.format(" %s=\"%s\"", token.name(), method.invoke(this));
} catch (IllegalAccessException ignored) {
} catch (InvocationTargetException ignored) {
}
}
}
return result;
}
}
\ No newline at end of file
import java.util.Set;
import java.util.TreeSet;
import java.util.LinkedList;
aspect Errors {
coll Set<ErrorMessage> Program.errors()
[new TreeSet<ErrorMessage>()]
root Program;
TypeUse contributes error("Type '" + getID() + "' not found")
when decl() == null && !isToken()
to Program.errors();
TypeDecl contributes error("Type '" + getID() + "' is already declared")
when isAlreadyDeclared()
to Program.errors();
Component contributes error("Component '" + name()
+ "' is already declared for type '" + toTypeDecl() + "'")
when isAlreadyDeclared()
to Program.errors();
RelationComponent contributes
error("Role name missing for type '" + toTypeDecl() + "'")
when !isTargetOfDirectedRelation() && name().isEmpty()
to Program.errors();
RelationComponent contributes
error("The target of a directed relation cannot have a role name")
when isTargetOfDirectedRelation() && !getID().isEmpty()
to Program.errors();
RelationComponent contributes
error("The target of a directed relation may only have multiplicity 1")
when isTargetOfDirectedRelation() && !multiplicityOne()
to Program.errors();
}
aspect HelpAttributes {
inh Program ASTNode.program();
eq Program.getChild().program() = this;
inh boolean TypeUse.isToken();
eq Program.getChild().isToken() = false;
eq TokenComponent.getTypeUse().isToken() = true;
syn boolean RelationComponent.multiplicityOne() = false;
eq OneRelationComponent.multiplicityOne() = true;
syn boolean RelationComponent.multiplicityOpt() = false;
eq OptionalRelationComponent.multiplicityOpt() = true;
syn boolean RelationComponent.multiplicityMany() = false;
eq ManyRelationComponent.multiplicityMany() = true;
}
aspect ErrorMessage {
public class ErrorMessage implements Comparable<ErrorMessage> {
private final ASTNode node;
private final int line;
private final int col;
private final String message;
public ErrorMessage(ASTNode node, String message) {
this.node = node;
this.line = node.getStartLine();
this.col = node.getStartColumn();
this.message = message;
}
public ASTNode getNode() {
return node;
}
public int getLine() {
return line;
}
public int getCol() {
return col;
}
public String getMessage() {
return message;
}
public String toString() {
return "Line " + line + ", column " + col + ": " + message;
}
@Override
public int compareTo(ErrorMessage err) {
int n = line - err.line;
if (n != 0) {
return n;
}
n = col-err.col;
if (n != 0) {
return n;
}
return message.compareTo(err.message);
}
}
protected ErrorMessage ASTNode.error(String message) {
return new ErrorMessage(this, message);
}
}
\ No newline at end of file
%header {:
package org.jastadd.relast.ast;
:};
%goal goal;
\ No newline at end of file
Program goal =
type_decls.t relations.r {: return new Program(t, r); :}
| STRING_LITERAL STAR {: return new Program(); :}
;
List type_decls =
/* empty */ {: return new List(); :}
| type_decls.l type_decl.d {: return l.add(d); :}
;
TypeDecl type_decl =
ID type_decl_super.s components_opt.c SCOL
{: return new TypeDecl(ID, false, s, c); :}
| ABSTRACT ID type_decl_super.s components_opt.c SCOL
{: return new TypeDecl(ID, true, s, c); :}
;
Opt type_decl_super =
/* empty */ {: return new Opt(); :}
| COL s_type_use.u {: return new Opt(u); :}
;
SimpleTypeUse s_type_use =
ID {: return new SimpleTypeUse(ID); :}
;
TypeUse type_use =
s_type_use.u {: return u; :}
| parameterized_type_use.p {: return p; :}
;
ParameterizedTypeUse parameterized_type_use =
ID LT type_use_list.l GT {: return new ParameterizedTypeUse(ID, l); :}
;
List type_use_list =
type_use.u {: return new List().add(u); :}
| type_use_list.l COMMA type_use.u {: return l.add(u); :}
;
List components_opt =
/* empty */ {: return new List(); :}
| ASSIGN components.l {: return l; :}
;
List components =
{: return new List(); :}
| components.l component.c {: return l.add(c); :}
;
Component component =
ID COL s_type_use.u {: return new NormalComponent(ID, u); :}
| s_type_use.u {: return new NormalComponent(u.getID(), u); :}
// List
| ID COL s_type_use.u STAR {: return new ListComponent(ID, u); :}
| s_type_use.u STAR {: return new ListComponent(u.getID(), u); :}
// Opt
| LBRACKET ID COL s_type_use.u RBRACKET {: return new OptComponent(ID, u); :}
| LBRACKET s_type_use.u RBRACKET {: return new OptComponent(u.getID(), u); :}
// NTA
| SLASH ID COL s_type_use.u SLASH {: return new NTAComponent(ID, u); :}
| SLASH s_type_use.u SLASH {: return new NTAComponent(u.getID(), u); :}
// NTA Token (same as NTA)
| SLASH LT ID COL s_type_use.u GT SLASH {: return new NTAComponent(ID, u); :}
| SLASH LT s_type_use.u GT SLASH {: return new NTAComponent(u.getID(), u); :}
// Token
| LT ID COL type_use.u GT {: return new TokenComponent(ID, u); :}
| LT ID GT {: return new TokenComponent(ID, new SimpleTypeUse("String")); :}
;
List relations =
/* empty */ {: return new List(); :}
| relations.l relation.r {: return l.add(r); :}
;
Relation relation =
RELATION relation_comp.l direction relation_comp.r SCOL
{: return new Relation(l, direction, r); :}
;
RelationComponent relation_comp =
// One
s_type_use.u DOT ID {: return new OneRelationComponent(ID, u); :}
| s_type_use.u {: return new OneRelationComponent("", u); :}
// Optional
| s_type_use.u DOT ID QUESTION_MARK {: return new OptionalRelationComponent(ID, u); :}
| s_type_use.u QUESTION_MARK {: return new OptionalRelationComponent("", u); :}
// Many
| s_type_use.u DOT ID STAR {: return new ManyRelationComponent(ID, u); :}
| s_type_use.u STAR {: return new ManyRelationComponent("", u); :}
;
Direction direction =
RIGHT {: return new RightDirection(); :}
| BIDIRECTIONAL {: return new Bidirectional(); :}
;
package org.jastadd.relast.compiler;
import org.jastadd.relast.ast.*;
import static org.jastadd.relast.compiler.Utils.filterToList;
import java.io.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.regex.Pattern;
import org.jastadd.relast.compiler.options.CommandLine;
import org.jastadd.relast.compiler.options.EnumOption;
import org.jastadd.relast.compiler.options.FlagOption;
import org.jastadd.relast.compiler.options.Option;
import org.jastadd.relast.compiler.options.StringOption;
import org.jastadd.relast.compiler.options.CommandLine.CommandLineException;
import beaver.Parser;
public class Compiler {
protected ArrayList<Option<?>> options;
protected FlagOption optionWriteToFile;
protected FlagOption optionPrintAST;
protected StringOption optionListClass;
protected CommandLine commandLine;
public Compiler(String args[]) throws CommandLineException {
options = new ArrayList<>();
addOptions();
commandLine = new CommandLine(options);
commandLine.parse(args);
if (commandLine.getArguments().size() != 1) {
error("specify one input file");
}
String filename = commandLine.getArguments().get(0);
Program p = parseProgram(filename);
if (!p.errors().isEmpty()) {
if (optionPrintAST.isSet()) {
System.out.println(p.dumpTree());
}
System.err.println("Errors:");
for (ErrorMessage e: p.errors()) {
System.err.println(e);
}
System.exit(1);
} else {
if (optionListClass.isSet()) {
System.out.println("ListClass is set to " + optionListClass.getValue());
p.listClass = optionListClass.getValue();
}
if (optionWriteToFile.isSet()) {
File file = new File(filename);
String absPath = file.getAbsolutePath();
String absPathExclExt = absPath.substring(0, absPath.lastIndexOf('.'));
writeToFile(absPathExclExt + "Gen.ast", p.generateAbstractGrammar());
writeToFile(absPathExclExt + "Gen.jadd", p.generateAspect());
} else if (optionPrintAST.isSet()) {
System.out.println(p.dumpTree());
} else {
System.out.println(p.generateAbstractGrammar());
System.out.println(p.generateAspect());
}
}
}
protected void writeToFile(String filename, String str) {
try {
PrintWriter writer = new PrintWriter(filename);
writer.print(str);
writer.close();
} catch (Exception e) {
e.printStackTrace();
System.exit(1);
}
}
protected void addOptions() {
optionWriteToFile = addOption(new FlagOption("file", "write output to files <filename>Gen.ast and <filename>Gen.jadd"));
optionPrintAST = addOption(new FlagOption("ast", "print AST"));
optionListClass = addOption(new StringOption("listClass", "determine the class name of the nonterminal reference list"));
}
protected <OptionType extends Option<?>> OptionType addOption(OptionType option) {
options.add(option);
return option;
}
private Program parseProgram(String file) {
FileReader reader = null;
try {
reader = new FileReader(file);
} catch (FileNotFoundException e) {
System.err.println(e.getMessage());
System.exit(1);
}
return parse(reader, file);
}
private Program parse(Reader reader, String file) {
RelAstScanner scanner = new RelAstScanner(reader);
RelAstParser parser = new RelAstParser();
try {
return (Program) parser.parse(scanner);
} catch (IOException e) {
error(e.getMessage());
} catch (Parser.Exception e) {
System.err.println("Parse error in file " + file);
System.err.println(e.getMessage());
System.exit(1);
}
return null;
}
protected void error(String message) {
System.err.println("Error: " + message);
System.err.println();
System.err.println("Usage: java -jar relast-compiler.jar <filename> [--option1] [--option2=value] ... ");
System.err.println("Options:");
System.err.print(commandLine.printOptionHelp());
System.exit(1);
}
public static void main(String[] args) {
try {
new Compiler(args);
} catch (CommandLineException e) {
System.out.println(e.getMessage());
System.exit(1);
}
}
}
package org.jastadd.relast.compiler.options;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.TreeSet;
public class CommandLine {
private final Collection<Option<?>> options;
private final Map<String, Option<?>> mapping;
private final List<String> arguments;
public CommandLine(Collection<Option<?>> options) {
this.options = options;
this.mapping = new HashMap<>();
for (Option<?> option: options) {
mapping.put(option.getName(), option);
}
this.arguments = new ArrayList<>();
}
public void parse(String args[]) throws CommandLineException {
int i = 0;
while (i < args.length) {
if (args[i].startsWith(Option.PREFIX)) {
int argumentIndex = args[i].indexOf("=");
String name;
String argument = null;
if (argumentIndex > 0) {
name = args[i].substring(2, argumentIndex);
argument = args[i].substring(argumentIndex+1);
} else {
name = args[i].substring(2);
}
Option<?> option = mapping.get(name);
if (option == null) {
throw new CommandLineException("Option " + Option.PREFIX + name + " not found");
}
match(option, argument);
} else {
arguments.add(args[i]);
}
i++;
}
}
public void match(Option<?> option, String argument) throws CommandLineException {
try {
switch (option.hasArgument()) {
case NO:
if (argument == null) {
option.match(null);
} else {
throw new CommandLineException("Option " + option + " is not allowed to have an argument");
}
break;
case OPTIONAL:
option.match(argument);
break;
case YES:
if (argument != null) {
option.match(argument);
} else {
throw new CommandLineException("Option " + option + " requires an argument");
}
break;
}
} catch (Option.IllegalMatchException e) {
throw new CommandLineException("Invalid value for option " + option + ": " + e.getMessage());
}
}
public List<String> getArguments() {
return arguments;
}
public String printOptionHelp() {
StringBuilder sb = new StringBuilder();
int longestOption = 0;
for (Option<?> option: options) {
if (longestOption < option.getName().length()) {
longestOption = option.getName().length();
}
}
for (Option<?> option: new TreeSet<>(options)) {
String s = String.format(" %s%-" + (longestOption+6) + "s %s%n",
Option.PREFIX, option.getName(), option.getDescription());
sb.append(s);
}
return sb.toString();
}
public static class CommandLineException extends Exception {
private static final long serialVersionUID = 1L;
public CommandLineException(String message) {
super(message);
}
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment