From 0fbf8618466d65c2e1907e597b27aa1c041edc36 Mon Sep 17 00:00:00 2001
From: Niklas Fors <niklas.fors@cs.lth.se>
Date: Tue, 3 Jul 2018 14:52:20 +0200
Subject: [PATCH] Add code generation for abstract grammar and fix bug

---
 spec/jastadd/Analysis.jrag                    | 44 ++++++++++---
 spec/jastadd/Backend.jadd                     | 61 +++++++++++++++++++
 spec/jastadd/Errors.jrag                      |  2 +-
 spec/parser/RelAstBase.parser                 |  2 +-
 .../org/jastadd/relast/compiler/Compiler.java |  2 +-
 5 files changed, 99 insertions(+), 12 deletions(-)
 create mode 100644 spec/jastadd/Backend.jadd

diff --git a/spec/jastadd/Analysis.jrag b/spec/jastadd/Analysis.jrag
index b7b0b8c..6972b05 100644
--- a/spec/jastadd/Analysis.jrag
+++ b/spec/jastadd/Analysis.jrag
@@ -18,7 +18,17 @@ aspect TypeAnalysis {
 }
 
 aspect ComponentAnalysis {
+	syn boolean Component.isDeclaringName() = true;
+	eq RelationComponent.isDeclaringName() = !isTargetOfRightDirection();
+	inh boolean RelationComponent.isTargetOfRightDirection();
+	eq Relation.getRight().isTargetOfRightDirection()
+		= getDirection() instanceof RightDirection;
+	eq Program.getChild().isTargetOfRightDirection() = false;
+
 	syn String Component.name() {
+		if (!isDeclaringName()) {
+			return "";
+		}
 		if (!getID().isEmpty()) {
 			return getID();
 		}
@@ -32,14 +42,18 @@ aspect ComponentAnalysis {
 	eq Program.getChild().otherRelationSideName()
 		= "";
 
-	syn TypeDecl Component.typeDecl() = enclosingTypeDecl();
-	eq RelationComponent.typeDecl() = getTypeUse().decl();
+	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 TypeDecl RelationComponent.ofTypeDecl();
+	eq Relation.getLeft().ofTypeDecl() = getRight().toTypeDecl();
+	eq Relation.getRight().ofTypeDecl() = getLeft().toTypeDecl();
+	eq Program.getChild().ofTypeDecl() = null;
 
 	syn boolean Component.isAlreadyDeclared()
-		= lookupComponent(typeDecl(), name()) != this;
+		= isDeclaringName() && lookupComponent(toTypeDecl(), name()) != this;
 	inh Component Component.lookupComponent(TypeDecl td, String name);
 	eq Program.getChild().lookupComponent(TypeDecl td, String name) {
 		if (td != null) {
@@ -50,15 +64,27 @@ aspect ComponentAnalysis {
 			}
 		}
 		for (Relation r: getRelations()) {
-			if (r.getLeft().typeDecl() == td && r.getLeft().name().equals(name)) {
-				return r.getLeft();
-			}
-			if (r.getRight().typeDecl() == td && r.getRight().name().equals(name)) {
-				return r.getRight();
-			}
+			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)
+		= isDeclaringName() && toTypeDecl() == td && name().equals(name)
+		? this
+		: null;
+
+
+	coll Set<RelationComponent> TypeDecl.relationComponents()
+		[new HashSet<RelationComponent>()]
+		root Program;
+	RelationComponent contributes this
+		when isDeclaringName() && toTypeDecl() != null
+		to TypeDecl.relationComponents()
+		for toTypeDecl();
 }
 
 aspect Utils {
diff --git a/spec/jastadd/Backend.jadd b/spec/jastadd/Backend.jadd
new file mode 100644
index 0000000..3aee5c4
--- /dev/null
+++ b/spec/jastadd/Backend.jadd
@@ -0,0 +1,61 @@
+aspect BackendAbstractGrammar {
+	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 TokenComponent.generateAbstractGrammar() {
+		return "<" + getID() + ":" + getTypeUse() + ">";
+	}
+
+	public String RelationComponent.generateAbstractGrammar() {
+		return "<_impl_" + getID() + ":" + ofTypeDecl() + ">";
+	}
+	public String ManyRelationComponent.generateAbstractGrammar() {
+		return "<_impl_" + getID() + ":MySet<" + ofTypeDecl() + ">>";
+	}
+}
\ No newline at end of file
diff --git a/spec/jastadd/Errors.jrag b/spec/jastadd/Errors.jrag
index a997303..3aa6ff2 100644
--- a/spec/jastadd/Errors.jrag
+++ b/spec/jastadd/Errors.jrag
@@ -16,7 +16,7 @@ aspect Errors {
 		to Program.errors();
 
 	Component contributes error("Component '" + name()
-			+ "' is already declared for type '" + typeDecl() + "'")
+			+ "' is already declared for type '" + toTypeDecl() + "'")
 		when isAlreadyDeclared()
 		to Program.errors();
 }
diff --git a/spec/parser/RelAstBase.parser b/spec/parser/RelAstBase.parser
index 291055d..3948cf2 100644
--- a/spec/parser/RelAstBase.parser
+++ b/spec/parser/RelAstBase.parser
@@ -66,7 +66,7 @@ RelationComponent relation_comp =
 	| LBRACKET type_use.u DOT ID RBRACKET {: return new OptionalRelationComponent(ID, u); :}
 	| LBRACKET type_use.u RBRACKET {: return new OptionalRelationComponent("", u); :}
 	// Many
-	| type_use.u STAR DOT ID {: return new ManyRelationComponent(ID, u); :}
+	| type_use.u DOT ID STAR {: return new ManyRelationComponent(ID, u); :}
 	| type_use.u STAR {: return new ManyRelationComponent("", u); :}
 	;
 
diff --git a/src/java/org/jastadd/relast/compiler/Compiler.java b/src/java/org/jastadd/relast/compiler/Compiler.java
index e5692ee..4fd6591 100644
--- a/src/java/org/jastadd/relast/compiler/Compiler.java
+++ b/src/java/org/jastadd/relast/compiler/Compiler.java
@@ -40,7 +40,7 @@ public class Compiler {
 			}
 			System.exit(1);
 		} else {
-			System.out.println(p.dumpTree());
+			System.out.println(p.generateAbstractGrammar());
 		}
 /*		} else {
 			if (optionPrintDot.isSet()) {
-- 
GitLab