Skip to content
Snippets Groups Projects
Commit 83593f23 authored by Jesper's avatar Jesper
Browse files

Generalize handling of implicit collection roots

Allow implicit root type for collection attributes when the grammar has
multiple root types.

If there are multiple roots in the grammar, the collection root type is set to
ASTNode.

Factored out root finding in collection attribute templates.

fixes #294 (bitbucket)
parent 2e08b92f
No related branches found
No related tags found
No related merge requests found
2019-03-18 Jesper Öqvist <jesper.oqvist@cs.lth.se>
* Allow implicit root type for collection attributes in grammars with
multiple root types.
2018-06-14 Jesper Öqvist <jesper.oqvist@cs.lth.se> 2018-06-14 Jesper Öqvist <jesper.oqvist@cs.lth.se>
* Removed generation of the is$Equal method. The method was unused. * Removed generation of the is$Equal method. The method was unused.
......
...@@ -43,15 +43,6 @@ aspect ASTErrors { ...@@ -43,15 +43,6 @@ aspect ASTErrors {
[new LinkedList<Problem>()] [new LinkedList<Problem>()]
root Grammar; root Grammar;
syn boolean TypeDecl.isRootNode() = false;
eq ASTDecl.isRootNode() = isPotentialRootNode() && parents().isEmpty();
syn boolean TypeDecl.isPotentialRootNode() = false;
eq ASTDecl.isPotentialRootNode() =
!hasAbstract() && !isASTNodeDecl() && !isOptSubtype() && !isListSubtype();
Grammar contributes Problem.builder() Grammar contributes Problem.builder()
.message("there is no root node in the grammar!") .message("there is no root node in the grammar!")
.buildWarning() .buildWarning()
......
...@@ -461,22 +461,6 @@ aspect AttributeProblems { ...@@ -461,22 +461,6 @@ aspect AttributeProblems {
return error(msg); return error(msg);
} }
CollDecl contributes multipleRootsProblem()
when hasMultipleRootsProblem()
to TypeDecl.attributeProblems()
for hostClass();
syn boolean CollDecl.hasMultipleRootsProblem() = root == null && grammar().roots().size() > 1;
syn Problem CollDecl.multipleRootsProblem() {
StringBuilder buf = new StringBuilder();
buf.append("multiple tree roots to search for contributions. Please explicitly select one of");
for (ASTDecl decl : grammar().roots()) {
buf.append(" " + decl.name());
}
return error(buf.toString());
}
CollDecl contributes error("No tree roots to search for contributions. " CollDecl contributes error("No tree roots to search for contributions. "
+ "Please declare an explicit root node.") + "Please declare an explicit root node.")
when hasNoRootProblem() when hasNoRootProblem()
......
/* Copyright (c) 2005-2016, The JastAdd Team /* Copyright (c) 2005-2019, The JastAdd Team
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
...@@ -39,6 +39,9 @@ aspect CollectionAttributes { ...@@ -39,6 +39,9 @@ aspect CollectionAttributes {
/** @return the type name of the collection root node */ /** @return the type name of the collection root node */
syn String CollDecl.rootType() = root().name(); syn String CollDecl.rootType() = root().name();
/** Returns {@code true} if the declaration does not have an explicit root type. */
syn boolean CollDecl.implicitRoot() = root == null;
/** @return the type name of the collection root node */ /** @return the type name of the collection root node */
syn String CollEq.rootType() = decl().rootType(); syn String CollEq.rootType() = decl().rootType();
...@@ -134,9 +137,18 @@ aspect CollectionAttributes { ...@@ -134,9 +137,18 @@ aspect CollectionAttributes {
} }
} }
syn TypeDecl AttrDecl.root() = grammar().root(); syn TypeDecl CollDecl.root() {
if (root != null) {
eq CollDecl.root() = root != null ? grammar().lookup(root) : super.root(); return grammar().lookup(root);
} else {
Collection<ASTDecl> roots = grammar().roots();
if (roots.size() == 1) {
return roots.iterator().next();
} else {
return grammar().lookup(config().astNodeType());
}
}
}
// Only used by circular collection attributes. // Only used by circular collection attributes.
public void AttrDecl.emitCircularCollectionEval(PrintStream out) { public void AttrDecl.emitCircularCollectionEval(PrintStream out) {
...@@ -428,6 +440,10 @@ aspect CollectionAttributes { ...@@ -428,6 +440,10 @@ aspect CollectionAttributes {
return s.toString(); return s.toString();
} }
/**
* Finds all roots in the grammar.
* A root is not a child of any other node.
*/
syn lazy Collection<ASTDecl> Grammar.roots() { syn lazy Collection<ASTDecl> Grammar.roots() {
Collection<ASTDecl> roots = new HashSet<ASTDecl>(); Collection<ASTDecl> roots = new HashSet<ASTDecl>();
for (TypeDecl decl : getTypeDeclList()) { for (TypeDecl decl : getTypeDeclList()) {
...@@ -438,7 +454,18 @@ aspect CollectionAttributes { ...@@ -438,7 +454,18 @@ aspect CollectionAttributes {
return roots; return roots;
} }
syn ASTDecl Grammar.root() = roots().isEmpty() ? null : roots().iterator().next(); /**
* Returns {@code true} if this type is a root in the abstract grammar.
* A root is not abstract and not a child of any other type in the grammar.
*/
syn boolean TypeDecl.isRootNode() = false;
eq ASTDecl.isRootNode() = isPotentialRootNode() && parents().isEmpty();
syn boolean TypeDecl.isPotentialRootNode() = false;
eq ASTDecl.isPotentialRootNode() =
!hasAbstract() && !isASTNodeDecl() && !isOptSubtype() && !isListSubtype();
eq ASTDecl.getCollDecl().hostClass() = this; eq ASTDecl.getCollDecl().hostClass() = this;
......
# Copyright (c) 2013-2015, The JastAdd Team # Copyright (c) 2013-2019, The JastAdd Team
# All rights reserved. # All rights reserved.
# #
# Redistribution and use in source and binary forms, with or without # Redistribution and use in source and binary forms, with or without
...@@ -25,6 +25,22 @@ ...@@ -25,6 +25,22 @@
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE. # POSSIBILITY OF SUCH DAMAGE.
CollDecl.findRoot [[
$if(#implicitRoot)
$ASTNode node = this;
while (node.getParent() != null) {
node = node.getParent();
}
$else
$ASTNode node = this;
while (node != null && !(node instanceof #rootType)) {
node = node.getParent();
}
$endif
$include(CollDecl.collDebugCheck)
#rootType root = (#rootType) node;
]]
CollDecl.collDebugCheck [[ CollDecl.collDebugCheck [[
$if(DebugMode) $if(DebugMode)
if (node == null) { if (node == null) {
...@@ -37,12 +53,7 @@ $endif ...@@ -37,12 +53,7 @@ $endif
CollDecl.computeMethod:onePhase [[ CollDecl.computeMethod:onePhase [[
/** @apilevel internal */ /** @apilevel internal */
private #getType #(name)_compute() { private #getType #(name)_compute() {
$ASTNode node = this; $include(CollDecl.findRoot)
while (node != null && !(node instanceof #rootType)) {
node = node.getParent();
}
$include(CollDecl.collDebugCheck)
#rootType root = (#rootType) node;
root.survey_#collectionId(); root.survey_#collectionId();
if (#(signature)_value == null) { if (#(signature)_value == null) {
#(signature)_value = $BottomValue; #(signature)_value = $BottomValue;
...@@ -54,12 +65,7 @@ CollDecl.computeMethod:onePhase [[ ...@@ -54,12 +65,7 @@ CollDecl.computeMethod:onePhase [[
CollDecl.computeMethod:twoPhase [[ CollDecl.computeMethod:twoPhase [[
/** @apilevel internal */ /** @apilevel internal */
private #getType #(name)_compute() { private #getType #(name)_compute() {
$ASTNode node = this; $include(CollDecl.findRoot)
while (node != null && !(node instanceof #rootType)) {
node = node.getParent();
}
$include(CollDecl.collDebugCheck)
#rootType root = (#rootType) node;
root.survey_#collectionId(); root.survey_#collectionId();
#getType _computedValue = $BottomValue; #getType _computedValue = $BottomValue;
$include(CollDecl.collectContributions) $include(CollDecl.collectContributions)
...@@ -69,7 +75,7 @@ CollDecl.computeMethod:twoPhase [[ ...@@ -69,7 +75,7 @@ CollDecl.computeMethod:twoPhase [[
CollDecl.collectContributions [[ CollDecl.collectContributions [[
if (root.contributorMap_#collectionId.containsKey(this)) { if (root.contributorMap_#collectionId.containsKey(this)) {
for ($ASTNode contributor : root.contributorMap_#collectionId.get(this)) { for ($ASTNode contributor : (java.util.Set<$ASTNode>) root.contributorMap_#collectionId.get(this)) {
contributor.contributeTo_#(signature)(_computedValue); contributor.contributeTo_#(signature)(_computedValue);
} }
} }
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment