Commit 0311cae7 authored by Johannes Mey's avatar Johannes Mey
Browse files

Merge branch 'dev/rene' into feature/relast. this required many adaptations.

parent b5551dc7
apply plugin: 'java'
apply plugin: 'jastadd'
apply plugin: 'application'
apply plugin: "idea"
sourceCompatibility = 1.8
......@@ -20,13 +23,11 @@ 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:${jackson_version}"
compile "com.fasterxml.jackson.core:jackson-databind:${jackson_version}"
compile 'com.fasterxml.jackson.core:jackson-core:2.9.8'
compile 'com.fasterxml.jackson.core:jackson-databind:2.9.8'
compile 'org.jastadd:jastadd:2.3.4'
runtime 'org.jastadd:jastadd:2.3.4'
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 {
......@@ -52,6 +53,39 @@ jar {
}
}
task relast(type: JavaExec) {
group = 'Build'
main = "-jar"
doFirst {
delete "src/gen/jastadd/*.ast"
delete "src/gen/jastadd/Ros2Rag.jadd"
delete "src/gen/jastadd/Ros2RagRefResolver.jadd"
delete "src/gen/jastadd/Ros2RagResolverStubs.jrag"
mkdir "src/gen/jastadd/"
}
args = [
"../libs/relast.jar",
"./src/main/jastadd/RelAst.relast",
"./src/main/jastadd/Ros2Rag.relast",
"--listClass=java.util.ArrayList",
"--jastAddList=JastAddList",
"--useJastAddNames",
"--file",
"--resolverHelper",
"--grammarName=./src/gen/jastadd/RelAST"
]
inputs.files file("../libs/relast.jar"),
file("src/main/jastadd/RelAST.relast"),
file("src/main/jastadd/Ros2Rag.relast")
outputs.files file("./src/gen/jastadd/RelAst.ast"),
file("src/gen/jastadd/RelAst.jadd"),
file("src/gen/jastadd/RelAstRefResolver.jadd"),
file('src/gen/jastadd/RelAstResolverStubs.jrag')
}
jastadd {
configureModuleBuild()
modules {
......@@ -65,10 +99,13 @@ jastadd {
}
jastadd {
basedir "src/main/jastadd/"
include "**/*.ast"
include "**/*.jadd"
include "**/*.jrag"
basedir "."
include "src/main/jastadd/**/*.ast"
include "src/main/jastadd/**/*.jadd"
include "src/main/jastadd/**/*.jrag"
include "src/gen/jastadd/**/*.ast"
include "src/gen/jastadd/**/*.jadd"
include "src/gen/jastadd/**/*.jrag"
}
scanner {
......@@ -106,6 +143,7 @@ jastadd {
scanner.genDir = "src/gen/java/org/jastadd/ros2rag/scanner"
parser.genDir = "src/gen/java/org/jastadd/ros2rag/parser"
jastaddOptions = ["--lineColumnNumbers", "--safeLazy", "--visitCheck=true", "--rewrite=cnta", "--cache=all"]
jastaddOptions = ["--lineColumnNumbers", "--List=JastAddList", "--safeLazy", "--visitCheck=true", "--rewrite=cnta", "--cache=all"]
}
generateAst.dependsOn relast
import java.util.*;
aspect Analysis {
aspect TypeAnalysis {
public abstract TypeUse Component.getTypeUse();
//--- lookupType ---
syn TypeDecl TypeUse.decl() = lookupType(getID());
inh TypeDecl TypeUse.lookupType(String name);
inh TypeDecl TypeDecl.lookupType(String name);
eq Program.getChild().lookupType(String name) {
for (TypeDecl td : getTypeDecls()) {
if (td.getID().equals(name)) {
return td;
}
}
return null;
}
//--- isAlreadyDeclared ---
syn boolean TypeDecl.isAlreadyDeclared() = lookupType(getID()) != this;
}
aspect ComponentAnalysis {
//--- isTargetOfDirectedRelation ---
inh boolean Component.isTargetOfDirectedRelation();
eq Relation.getRight().isTargetOfDirectedRelation() = getDirection() instanceof RightDirection;
eq Program.getChild().isTargetOfDirectedRelation() = false;
//--- name ---
syn String Component.name() = getID();
//--- enclosingTypeDecl ---
inh TypeDecl Component.enclosingTypeDecl();
eq TypeDecl.getChild().enclosingTypeDecl() = this;
eq Program.getChild().enclosingTypeDecl() = null;
//--- otherSide ---
inh RelationComponent RelationComponent.opposite();
eq Relation.getLeft().opposite() = getRight();
eq Relation.getRight().opposite() = getLeft();
eq Program.getChild().opposite() = null;
//--- ofTypeDecl ---
syn TypeDecl RelationComponent.ofTypeDecl() = opposite().getTypeUse().decl();
//--- isAlreadyDeclared ---
/**
* Check, if role with the same name is already declared on the same nonterminal
*/
syn boolean RelationComponent.isAlreadyDeclared()
= !isTargetOfDirectedRelation() /* if unnamed in relation, there is no role name, so no error */
&& getTypeUse().decl() != null /* nonterminal type of role is defined */
&& findComponent(getTypeUse().decl(), name()) != this; /* there is another role defined previously with the same name */
//--- findComponent ---
/** Search for either a component on the RHS of the given type with the given name,
* or a relation part for the given type and a role with the given name */
inh Component Component.findComponent(TypeDecl td, String name);
eq Program.getChild().findComponent(TypeDecl td, String name)
= findComponentSyn(td, name);
syn Component Program.findComponentSyn(TypeDecl td, String name) {
for (Component c: td.getComponents()) {
if (c.name().equals(name)) {
return c;
}
}
for (Relation r : getRelations()) {
if (r.getLeft().matches(td, name))
return r.getLeft();
if (r.getRight().matches(td, name))
return r.getRight();
}
return null;
}
//--- isInvalidRedefinition ---
/**
* Check, if a component with the same name is already declared in some supertype
*/
syn boolean Component.isInvalidRedefinition() = invalidRedefinition() != null;
/**
* Check, if a component with the same name is already declared in some supertype, and return it, if any
*/
syn Component Component.invalidRedefinition() = null;
eq TokenComponent.invalidRedefinition() = invalidRedefinitionOn(enclosingTypeDecl());
eq RelationComponent.invalidRedefinition() = invalidRedefinitionOn(getTypeUse().decl());
syn Component Component.invalidRedefinitionOn(TypeDecl td) {
if (td == null) return null;
while (td.hasSuper() && td.getSuper().decl() != null) {
td = td.getSuper().decl();
// find a matching component on the RHS of the (current) super type
Component c = findComponent(td, getID());
if (c != null && !this.isEqual(c)) return c;
}
return null;
}
//--- isEqual ---
syn boolean Component.isEqual(Component c) = this.getClass() == c.getClass() && getTypeUse().isEqual(c.getTypeUse());
/**
* TokenComponents may be specialized by NTATokenComponents and vice versa
*/
eq TokenComponent.isEqual(Component c) = (c instanceof TokenComponent) && getTypeUse().isEqual(c.getTypeUse());
syn boolean TypeUse.isEqual(TypeUse u);
eq SimpleTypeUse.isEqual(TypeUse u) = u instanceof SimpleTypeUse && getID().equals(u.getID());
eq ParameterizedTypeUse.isEqual(TypeUse u) {
if (!getID().equals(u.getID())) return false;
if (!(u instanceof ParameterizedTypeUse)) return false;
ParameterizedTypeUse pu = (ParameterizedTypeUse) u;
if (getNumTypeUse() != pu.getNumTypeUse()) return false;
for (int i = 0; i < getNumTypeUse(); i++) {
if (!getTypeUse(i).isEqual(pu.getTypeUse(i))) return false;
}
return true;
}
//--- matches ---
/**
* @return true, if the component has both type and role, its type matches the given typeDecl and its name matches the given name
*/
syn boolean RelationComponent.matches(TypeDecl td, String name)
= !isTargetOfDirectedRelation() && getTypeUse().decl() == td && name().equals(name);
//--- relationComponents ---
coll Set<RelationComponent> TypeDecl.relationComponents()
[new HashSet<RelationComponent>()]
root Program;
RelationComponent contributes this
when !isTargetOfDirectedRelation() && getTypeUse().decl() != null
to TypeDecl.relationComponents()
for getTypeUse().decl();
//--- relationComponentsTransitive ---
syn Collection<RelationComponent> TypeDecl.relationComponentsTransitive() {
Collection<RelationComponent> list = new ArrayList<>();
if (hasSuper() && getSuper().decl() != null) {
list.addAll(getSuper().decl().relationComponentsTransitive());
}
list.addAll(relationComponents());
return list;
}
//--- oneRelationComponents ---
syn Set<OneRelationComponent> TypeDecl.oneRelationComponents() {
Set<OneRelationComponent> set = new HashSet<>();
for (RelationComponent rc: relationComponents()) {
if (rc instanceof OneRelationComponent) {
set.add((OneRelationComponent) rc);
}
}
return set;
}
//--- needUnresolvedClass ---
syn boolean TypeDecl.needUnresolvedClass() {
// a TypeDecl needs an unresolved class, if it can appear in a relation
// TODO
return true;
}
//--- isList ---
syn boolean Component.isList() = false;
eq ListComponent.isList() = true;
eq NTAListComponent.isList() = true;
eq ManyRelationComponent.isList() = true;
//--- isOpt ---
syn boolean Component.isOpt() = false;
eq OptComponent.isOpt() = true;
eq NTAOptComponent.isOpt() = true;
eq OptionalRelationComponent.isOpt() = true;
//--- isNullable ---
syn boolean Component.isNullable() = false;
eq TokenComponent.isNullable() = !"float double int short long char byte boolean".contains(getTypeUse().getID());
}
aspect InstanceSupplier {
//--- program ---
inh Program TypeDecl.program();
eq Program.getTypeDecl(int i).program() = this;
//--- subTypeDecls ---
syn Collection<TypeDecl> TypeDecl.subTypeDecls() {
Collection<TypeDecl> subDecls = new ArrayList();
for (TypeDecl decl : program().getTypeDeclList()) {
if (decl.hasSuper() && decl.getSuper().getID().equals(getID())) {
subDecls.add(decl);
}
}
return subDecls;
}
//--- instantiableSubType ---
syn TypeDecl TypeDecl.instantiableSubType() {
if (getAbstract() == false) {
return this;
} else {
for (TypeDecl sub : subTypeDecls()) {
if (sub.getAbstract() == false) {
return sub;
} else {
TypeDecl subInstance = sub.instantiableSubType();
if (subInstance != null) {
return subInstance;
}
}
}
}
return null;
}
}
aspect Constructors {
//--- componentsTransitive ---
syn Collection<Component> TypeDecl.componentsTransitive() {
ArrayList<Component> list = new ArrayList<>();
if (hasSuper() && getSuper().decl() != null) {
list.addAll(getSuper().decl().componentsTransitive());
}
for (Component c: getComponents()) {
if (c.inConstructor()) {
list.add(c);
}
}
return list;
}
//--- needsConstructor ---
syn boolean TypeDecl.needsConstructor() = !componentsTransitive().isEmpty() && !relationComponentsTransitive().isEmpty();
//--- inConstructor ---
/**
* @return true, if the component should be added to the constructor (i.e., is not an NTA)
*/
syn boolean Component.inConstructor() = true;
eq NTAComponent.inConstructor() = false;
eq NTAOptComponent.inConstructor() = false;
eq NTAListComponent.inConstructor() = false;
eq NTATokenComponent.inConstructor() = false;
}
aspect Utils {
//--- toString ---
public String SimpleTypeUse.toString() {
return getID();
}
public String ParameterizedTypeUse.toString() {
StringBuilder sb = new StringBuilder();
sb.append(getID()).append("<");
boolean first = true;
for (TypeUse u: getTypeUses()) {
if (first) {
first = false;
} else {
sb.append(", ");
}
sb.append(u.toString());
}
sb.append(">");
return sb.toString();
}
public String TypeDecl.toString() {
return getID();
}
}
......@@ -33,7 +33,7 @@ aspect DumpTree {
public String ASTNode.extraDumpInfo() { return ""; }
public String ASTNode.getTokens() {
java.util.TreeSet<java.lang.reflect.Method> methods = new java.util.TreeSet<>(Comparator.comparing(java.lang.reflect.Method::getName));
java.util.TreeSet<java.lang.reflect.Method> methods = new java.util.TreeSet<>(java.util.Comparator.comparing(java.lang.reflect.Method::getName));
methods.addAll(java.util.Arrays.asList(getClass().getMethods()));
......
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();
RelationComponent contributes error("Role '" + name()
+ "' is already declared for type '" + getTypeUse().decl() + "'")
when isAlreadyDeclared()
to Program.errors();
RelationComponent contributes error("Role '" + name()
+ "' is an invalid redefinition for type '" + getTypeUse().decl() + "', conflicts with supertype '"
+ invalidRedefinition().enclosingTypeDecl() + "'")
when isInvalidRedefinition()
to Program.errors();
TokenComponent contributes error("Token '" + name()
+ "' is an invalid redefinition for type '" + enclosingTypeDecl() + "', conflicts with supertype '"
+ invalidRedefinition().enclosingTypeDecl() + "'")
when isInvalidRedefinition()
to Program.errors();
RelationComponent contributes
error("Role name missing for type '" + getTypeUse().decl() + "'")
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;
inh ContainedInFile Component.enclosingFileContainer();
eq TypeDecl.getComponent().enclosingFileContainer() = this;
eq Relation.getChild().enclosingFileContainer() = this;
inh ContainedInFile TypeUse.enclosingFileContainer();
eq SimpleTypeComponent.getTypeUse().enclosingFileContainer() = enclosingFileContainer();
eq TokenComponent.getTypeUse().enclosingFileContainer() = enclosingFileContainer();
eq TypeDecl.getSuper().enclosingFileContainer() = this;
syn String ASTNode.containedFile() = "Unknown";
eq Component.containedFile() = enclosingFileContainer() == null ? "Unknown2" : enclosingFileContainer().containedFile();
eq TypeUse.containedFile() = enclosingFileContainer() == null ? "Unknown3" : enclosingFileContainer().containedFile();
eq TypeDecl.containedFile() = getFileName();
eq Relation.containedFile() = getFileName();
}
aspect ErrorMessage {
public class ErrorMessage implements Comparable<ErrorMessage> {
private final ASTNode node;
private final String filename;
private final int line;
private final int col;
private final String message;
public ErrorMessage(ASTNode node, String message) {
this.node = node;
this.filename = node.containedFile();
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 filename + " Line " + line + ", column " + col + ": " + message;
}
@Override
public int compareTo(ErrorMessage err) {
int n = filename.compareTo(err.filename);
if (n != 0) {
return n;
}
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);
}
}
//import java.util.Set;
//import java.util.TreeSet;
//import java.util.LinkedList;
//
//
//
//
//aspect ErrorMessage {
// public class ErrorMessage implements Comparable<ErrorMessage> {
// private final ASTNode node;
// private final String filename;
// private final int line;
// private final int col;
// private final String message;
//
// public ErrorMessage(ASTNode node, String message) {
// this.node = node;
// this.filename = node.containedFile().getFileName();
// 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 filename + " Line " + line + ", column " + col + ": " + message;
// }
//
// @Override
// public int compareTo(ErrorMessage err) {
// int n = filename.compareTo(err.filename);
// if (n != 0) {
// return n;
// }
//
// 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);
// }
//}
aspect NameResolution {
refine RefResolverStubs eq ASTNode.globallyResolveTypeDeclByToken(String id) = program().resolveTypeDecl(id);
syn TypeDecl Program.resolveTypeDecl(String name) {
for (TypeDecl decl : typeDecls()) {
if (decl.getName().equals(name)) {
return decl;
}
}
throw new RuntimeException("TypeDecl " + name + " could not be resolved.");
}
}
aspect Navigation {
inh Program ASTNode.program();
eq Program.getChild().program() = this;
coll java.util.Set<TypeDecl> Program.typeDecls() [new java.util.HashSet<>()] root Program;
TypeDecl contributes this
to Program.typeDecls()
for program();
coll java.util.Set<Relation> Program.relations() [new java.util.HashSet<>()] root Program;
Relation contributes this
to Program.relations()
for program();
inh TypeDecl Component.containingTypeDecl();
eq TypeDecl.getChild().containingTypeDecl() = this;
// 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;
inh GrammarFile ASTNode.containedFile();
eq GrammarFile.getChild().containedFile() = this;
}
Program ::= TypeDecl* Relation*;
abstract ContainedInFile ::= <FileName> ;
TypeDecl : ContainedInFile ::= <ID> <Abstract:boolean> [Super:TypeUse] Component*;
abstract Component ::= <ID>;
abstract SimpleTypeComponent : Component ::= TypeUse:SimpleTypeUse;
NormalComponent : SimpleTypeComponent;
ListComponent : SimpleTypeComponent;
OptComponent : SimpleTypeComponent;
NTAComponent : SimpleTypeComponent;
NTAOptComponent : SimpleTypeComponent;
NTAListComponent : SimpleTypeComponent;
TokenComponent : Component ::= TypeUse;
NTATokenComponent : TokenComponent ::= TypeUse;
abstract TypeUse ::= <ID>;
SimpleTypeUse : TypeUse;
<