diff --git a/src/main/jastadd/Analysis.jrag b/src/main/jastadd/Analysis.jrag index a9d3711d89cfd7e4b2426e96dcdb9aa903ccdd44..62c0f54587f49d20f6c395b5e2341725a716c510 100644 --- a/src/main/jastadd/Analysis.jrag +++ b/src/main/jastadd/Analysis.jrag @@ -2,144 +2,144 @@ 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); + 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; - } + 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(); - } + 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(); - } + 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(); + } } diff --git a/src/main/jastadd/Backend.jadd b/src/main/jastadd/Backend.jadd index 835e9ec593d0fed28fb41ff2dc08d34d362b966f..1ddf8be562475a2606021c875fcd1eef22ee02d7 100644 --- a/src/main/jastadd/Backend.jadd +++ b/src/main/jastadd/Backend.jadd @@ -1,552 +1,552 @@ 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(); - } + 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"; - } + 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); + 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; + 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); - } + 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() + ".add"); - 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() + ".remove"); - 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(".get" + nameCapitalized() + "() {\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 get" + nameCapitalized() + "() != 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) { - // getXs - sb.append(ind(1) + "public java.util.List<" + ofTypeDecl() + "> " + toTypeDecl()); - sb.append(".get" + nameCapitalized() + "s() {\n"); - sb.append(ind(2) + "return get" + nameCapitalized() + "List();\n"); - sb.append(ind(1) + "}\n"); - - // getXList - sb.append(ind(1) + "public java.util.List<" + ofTypeDecl() + "> " + toTypeDecl()); - sb.append(".get" + nameCapitalized() + "List() {\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"); - } + 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() + ".add"); + 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() + ".remove"); + 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(".get" + nameCapitalized() + "() {\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 get" + nameCapitalized() + "() != 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) { + // getXs + sb.append(ind(1) + "public java.util.List<" + ofTypeDecl() + "> " + toTypeDecl()); + sb.append(".get" + nameCapitalized() + "s() {\n"); + sb.append(ind(2) + "return get" + nameCapitalized() + "List();\n"); + sb.append(ind(1) + "}\n"); + + // getXList + sb.append(ind(1) + "public java.util.List<" + ofTypeDecl() + "> " + toTypeDecl()); + sb.append(".get" + nameCapitalized() + "List() {\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() + ".add"); - 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() + ".remove"); - 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() + ".add"); - 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() + ".remove"); - 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); - } - } + 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() + ".add"); + 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() + ".remove"); + 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() + ".add"); + 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() + ".remove"); + 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 (get" + nameCapitalized() + "() == 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"); - } + 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 (get" + nameCapitalized() + "() == 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 "<->"; - } + 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; - } + public String ASTNode.ind(int n) { + String s = ""; + for (int i = 0; i < n; i++) { + s += " "; + } + return s; + } } diff --git a/src/main/jastadd/DumpTree.jrag b/src/main/jastadd/DumpTree.jrag index f49741e6fe607365f323846828b6735e4034d913..9193b9334fb63901d8dc985b5e5ba091e6a1e710 100644 --- a/src/main/jastadd/DumpTree.jrag +++ b/src/main/jastadd/DumpTree.jrag @@ -6,60 +6,60 @@ import java.lang.reflect.InvocationTargetException; // _ALL_ AST nodes and can cause collisions in the abstract grammar namespace. aspect DumpTree { - private static final String ASTNode.DUMP_TREE_INDENT = " "; + private static final String ASTNode.DUMP_TREE_INDENT = " "; - public String ASTNode.dumpTree() { - ByteArrayOutputStream bytes = new ByteArrayOutputStream(); - dumpTree(new PrintStream(bytes)); - return bytes.toString(); - } + 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) { + 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 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.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()); - } - }); + 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())); + 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; - } + 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 diff --git a/src/main/jastadd/Errors.jrag b/src/main/jastadd/Errors.jrag index e3f5d60308a10f1781b9b3fdf79f0c736971faf4..5cc6aedcbc3c699f8e3c38150177025c8fc90a64 100644 --- a/src/main/jastadd/Errors.jrag +++ b/src/main/jastadd/Errors.jrag @@ -3,103 +3,103 @@ 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(); + 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; + 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); - } + 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 diff --git a/src/main/jastadd/RelAst.flex b/src/main/jastadd/RelAst.flex index 7027e38d30d91163c1d6e6b948a6641a105421b1..d224f8d11b1dac7bee456509759667707310eac0 100644 --- a/src/main/jastadd/RelAst.flex +++ b/src/main/jastadd/RelAst.flex @@ -29,9 +29,9 @@ import org.jastadd.relast.parser.RelAstParser.Terminals; public static class ScannerError extends Error { - public ScannerError(String message) { - super(message); - } + public ScannerError(String message) { + super(message); + } } %} @@ -46,42 +46,42 @@ ID = [a-zA-Z$_][a-zA-Z0-9$_]* %% <YYINITIAL> { - {WhiteSpace} { /* ignore */ } - {Comment} { /* ignore */ } - - "abstract" { return sym(Terminals.ABSTRACT); } - "rel" { return sym(Terminals.RELATION); } - - ";" { return sym(Terminals.SCOL); } - ":" { return sym(Terminals.COL); } - "::=" { return sym(Terminals.ASSIGN); } - "*" { return sym(Terminals.STAR); } - "." { return sym(Terminals.DOT); } - "," { return sym(Terminals.COMMA); } - "<" { return sym(Terminals.LT); } - ">" { return sym(Terminals.GT); } - "[" { return sym(Terminals.LBRACKET); } - "]" { return sym(Terminals.RBRACKET); } - "/" { return sym(Terminals.SLASH); } - "?" { return sym(Terminals.QUESTION_MARK); } - "->" { return sym(Terminals.RIGHT); } - "<->" { return sym(Terminals.BIDIRECTIONAL); } - - // ID - {ID} { return sym(Terminals.ID); } - \" { stringLitSb.setLength(0); yybegin(STRING); } - <<EOF>> { return sym(Terminals.EOF); } + {WhiteSpace} { /* ignore */ } + {Comment} { /* ignore */ } + + "abstract" { return sym(Terminals.ABSTRACT); } + "rel" { return sym(Terminals.RELATION); } + + ";" { return sym(Terminals.SCOL); } + ":" { return sym(Terminals.COL); } + "::=" { return sym(Terminals.ASSIGN); } + "*" { return sym(Terminals.STAR); } + "." { return sym(Terminals.DOT); } + "," { return sym(Terminals.COMMA); } + "<" { return sym(Terminals.LT); } + ">" { return sym(Terminals.GT); } + "[" { return sym(Terminals.LBRACKET); } + "]" { return sym(Terminals.RBRACKET); } + "/" { return sym(Terminals.SLASH); } + "?" { return sym(Terminals.QUESTION_MARK); } + "->" { return sym(Terminals.RIGHT); } + "<->" { return sym(Terminals.BIDIRECTIONAL); } + + // ID + {ID} { return sym(Terminals.ID); } + \" { stringLitSb.setLength(0); yybegin(STRING); } + <<EOF>> { return sym(Terminals.EOF); } } <STRING> { - \" { yybegin(YYINITIAL); return sym(Terminals.STRING_LITERAL, stringLitSb.toString()); } - [^\n\r\"\\]+ { stringLitSb.append( yytext() ); } - \\t { stringLitSb.append('\t'); } - \\n { stringLitSb.append('\n'); } - \\r { stringLitSb.append('\r'); } - \\\" { stringLitSb.append('\"'); } - \\ { stringLitSb.append('\\'); } + \" { yybegin(YYINITIAL); return sym(Terminals.STRING_LITERAL, stringLitSb.toString()); } + [^\n\r\"\\]+ { stringLitSb.append( yytext() ); } + \\t { stringLitSb.append('\t'); } + \\n { stringLitSb.append('\n'); } + \\r { stringLitSb.append('\r'); } + \\\" { stringLitSb.append('\"'); } + \\ { stringLitSb.append('\\'); } } -[^] { throw new ScannerError((yyline+1) +"," + (yycolumn+1) + ": Illegal character <"+yytext()+">"); } +[^] { throw new ScannerError((yyline+1) +"," + (yycolumn+1) + ": Illegal character <"+yytext()+">"); } diff --git a/src/main/jastadd/RelAst.parser b/src/main/jastadd/RelAst.parser index 90992596d6938930c5c49f09e7e3d1e519c62302..27e0e7e35d179b8e4b4b3115f9132cd2b1f55bab 100644 --- a/src/main/jastadd/RelAst.parser +++ b/src/main/jastadd/RelAst.parser @@ -1,94 +1,94 @@ Program goal = - type_decls.t relations.r {: return new Program(t, r); :} - | STRING_LITERAL STAR {: return new Program(); :} - ; + 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); :} - ; + /* 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); :} - ; + 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); :} - ; + /* empty */ {: return new Opt(); :} + | COL s_type_use.u {: return new Opt(u); :} + ; SimpleTypeUse s_type_use = - ID {: return new SimpleTypeUse(ID); :} - ; + ID {: return new SimpleTypeUse(ID); :} + ; TypeUse type_use = - s_type_use.u {: return u; :} - | parameterized_type_use.p {: return p; :} - ; + 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); :} - ; + 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); :} - ; + 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; :} - ; + /* empty */ {: return new List(); :} + | ASSIGN components.l {: return l; :} + ; List components = - {: return new List(); :} - | components.l component.c {: return l.add(c); :} - ; + {: 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")); :} - ; + 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); :} - ; + /* 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); :} - ; + 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); :} - ; + // 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(); :} - ; + RIGHT {: return new RightDirection(); :} + | BIDIRECTIONAL {: return new Bidirectional(); :} + ; diff --git a/src/main/java/org/jastadd/relast/compiler/options/Option.java b/src/main/java/org/jastadd/relast/compiler/options/Option.java index b1789a5945aa1a414386f9f1536551e7b8f1ce81..e20354e973e5ec11568041291242c2699ec0ab4d 100644 --- a/src/main/java/org/jastadd/relast/compiler/options/Option.java +++ b/src/main/java/org/jastadd/relast/compiler/options/Option.java @@ -4,6 +4,7 @@ abstract public class Option<ValueType> implements Comparable<Option<?>> { public final static String PREFIX = "--"; private final String name; private final String description; + public Option(String name, String description) { this.name = name; this.description = description;