/** * Copyright 2004-2016 Riccardo Solmi. All rights reserved. * This file is part of the Whole Platform. * * The Whole Platform is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * The Whole Platform is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the Whole Platform. If not, see <http://www.gnu.org/licenses/>. */ package org.whole.lang.visitors; import java.util.Collection; import java.util.HashSet; import java.util.Set; import org.whole.lang.events.ReplaceChildTracker; import org.whole.lang.model.IEntity; import org.whole.lang.reflect.ILanguageKit; /** * @author Riccardo Solmi */ public class GenericTraversalFactory { public static final GenericTraversalFactory instance = new GenericTraversalFactory(); protected GenericTraversalFactory() { } public IVisitor failure() { return new GenericFailureVisitor(); } public IVisitor identity() { return new GenericIdentityVisitor(); } public IBinaryVisitor sequence(IVisitor visitor1, IVisitor visitor2) { return new GenericSequenceVisitor(visitor1, visitor2); } public IBinaryVisitor concurrentSequence(IVisitor visitor1, IVisitor visitor2) { return new GenericConcurrentSequenceVisitor(visitor1, visitor2); } public IBinaryVisitor ifThen(IVisitor condition, IVisitor success) { return new GenericIfThenVisitor(condition, success); } public IBinaryVisitor ifElse(IVisitor visitor1, IVisitor visitor2) { return new GenericIfElseVisitor(visitor1, visitor2); } public ITernaryVisitor ifThenElse(IVisitor condition, IVisitor success, IVisitor failure) { return new GenericIfThenElseVisitor(condition, success, failure); } public IUnaryVisitor not(IVisitor visitor) { return new GenericNotVisitor(visitor); } public IVisitor one(IVisitor... visitors) { return new AbstractQuantifiedVisitor(visitors) { public void visit(IEntity entity) { for (int i=0; i<visitorsLength(); i++) try { getVisitor(i).visit(entity); return; } catch (VisitException e) { } throw new VisitException(); } public void toString(StringBuilder sb) { sb.append("one"); super.toString(sb); } }; } public IVisitor some(IVisitor... visitors) { return new AbstractQuantifiedVisitor(visitors) { public void visit(IEntity entity) { boolean fail = true; for (int i=0; i<visitorsLength(); i++) try { getVisitor(i).visit(entity); fail = false; } catch (VisitException e) { } if (fail) throw new VisitException(); } public void toString(StringBuilder sb) { sb.append("some"); super.toString(sb); } }; } public IVisitor all(IVisitor... visitors) { return new AbstractQuantifiedVisitor(visitors) { public void visit(IEntity entity) { for (int i=0; i<visitorsLength(); i++) getVisitor(i).visit(entity); } public void toString(StringBuilder sb) { sb.append("all"); super.toString(sb); } }; } public IVisitor concurrentSome(IVisitor... visitors) { return new AbstractQuantifiedVisitor(visitors) { public void visit(IEntity entity) { ReplaceChildTracker tracker = new ReplaceChildTracker(entity); boolean fail = true; for (int i=0; i<visitorsLength(); i++) try { getVisitor(i).visit(tracker.entity()); fail = false; } catch (VisitException e) { } tracker.dispose(); if (fail) throw new VisitException(); } public void toString(StringBuilder sb) { sb.append("concurrentSome"); super.toString(sb); } }; } public IVisitor concurrentAll(IVisitor... visitors) { return new AbstractQuantifiedVisitor(visitors) { public void visit(IEntity entity) { ReplaceChildTracker tracker = new ReplaceChildTracker(entity); try { for (int i=0; i<visitorsLength(); i++) getVisitor(i).visit(tracker.entity()); } finally { tracker.dispose(); } } public void toString(StringBuilder sb) { sb.append("concurrentAll"); super.toString(sb); } }; } public IUnaryVisitor traverseOne(IVisitor visitor, final int startIndex) { return new AbstractUnaryVisitor<IVisitor>(visitor) { public void visit(IEntity entity) { for (int i=startIndex; i<entity.wSize(); i++) try { wGetVisitor1().visit(entity.wGet(i)); return; } catch (VisitException e) { } throw new VisitException(); } }; } public IUnaryVisitor traverseOne(IVisitor visitor, boolean includeAdjacents) { return includeAdjacents ? new GenericTraverseOneVisitor(visitor) : new GenericTraverseOneVisitor(visitor) { protected final int endIndex(IEntity entity) { return entity.wSize(); } }; } public IUnaryVisitor traverseOneAdjacent(IVisitor visitor) { return new GenericTraverseOneVisitor(visitor) { protected final int startIndex(IEntity entity) { return entity.wSize(); } }; } public IUnaryVisitor traverseSome(IVisitor visitor, boolean includeAdjacents) { return includeAdjacents ? new GenericTraverseSomeVisitor(visitor) : new GenericTraverseSomeVisitor(visitor) { protected final int endIndex(IEntity entity) { return entity.wSize(); } }; } public IUnaryVisitor traverseSomeAdjacents(IVisitor visitor) { return new GenericTraverseSomeVisitor(visitor) { protected final int startIndex(IEntity entity) { return entity.wSize(); } }; } public IUnaryVisitor traverseAll(IVisitor visitor, boolean includeAdjacents) { return includeAdjacents ? traverseAll(visitor) : traverseAllChildren(visitor); } public IUnaryVisitor traverseAll(IVisitor visitor) { return new GenericTraverseAllVisitor(visitor); } public IUnaryVisitor traverseAllChildren(IVisitor visitor) { return new GenericTraverseAllVisitor(visitor) { protected final int endIndex(IEntity entity) { return entity.wSize(); } }; } public IUnaryVisitor traverseAllAdjacents(IVisitor visitor) { return new GenericTraverseAllVisitor(visitor) { protected final int startIndex(IEntity entity) { return entity.wSize(); } }; } public IUnaryVisitor traverseParent(IVisitor visitor) { return new GenericTraverseParentVisitor(visitor); } //TODO ? add one, some, all variants public IUnaryVisitor traverseCollection(IVisitor condition, Collection collection) { return new GenericTraverseCollectionVisitor(condition, collection); } public IUnaryVisitor breadthFirst(IVisitor visitor) { IBinaryVisitor seq = sequence(visitor, null); seq.wSetVisitor2(new GenericBreadthFirstTraversalVisitor(seq)); return seq; } public IUnaryVisitor collect(IVisitor condition, Collection collection) { return new GenericCollectVisitor(condition, collection); } public IVisitor distinct(Set<IEntity> visitSet) { return new GenericDistinctVisitor(visitSet); } public IVisitor distinct() { return distinct(new HashSet<IEntity>()); } public IDynamicVariantVisitor dynamicVisitor() { return new DynamicCrossLanguageVariantVisitor(); } public IDynamicVariantVisitor dynamicVisitor(ILanguageKit languageKit) { return new DynamicMonoLanguageVariantVisitor(languageKit); } //*** derived *** //includes self public IBinaryVisitor ancestors(IVisitor visitor) { IBinaryVisitor result = sequence(visitor, null); result.wSetVisitor2(traverseParent(result)); return result; } public IBinaryVisitor ancestorsWhile(IVisitor visitor) { IBinaryVisitor result = ifThen(visitor, null); result.wSetVisitor2(traverseParent(result)); return result; } public IBinaryVisitor ancestorsUntil(IVisitor visitor) { IBinaryVisitor result = ifElse(visitor, null); result.wSetVisitor2(traverseParent(result)); return result; } public IUnaryVisitor tryPrune(IVisitor visitor) { return ifElse(visitor, identity()); } public IUnaryVisitor topDown(IVisitor visitor, boolean includeAdjacents) { IBinaryVisitor sequence = sequence(visitor, null); IBinaryVisitor result = includeAdjacents ? ifThen(distinct(), sequence) : sequence; sequence.wSetVisitor2(traverseAll(result, includeAdjacents)); return result; } public IUnaryVisitor concurrentTopDown(IVisitor visitor, boolean includeAdjacents) { IBinaryVisitor sequence = concurrentSequence(visitor, null); IBinaryVisitor result = includeAdjacents ? ifThen(distinct(), sequence) : sequence; sequence.wSetVisitor2(traverseAll(result, includeAdjacents)); return result; } public IUnaryVisitor topDownWhile(IVisitor visitor, boolean includeAdjacents) { IBinaryVisitor result = ifThen( includeAdjacents ? sequence(distinct(), visitor) : visitor, null); result.wSetVisitor2(traverseAll(result, includeAdjacents)); return result; } public IUnaryVisitor topDownUntil(IVisitor visitor, boolean includeAdjacents) { IBinaryVisitor ifElse = ifElse(visitor, null); IBinaryVisitor result = includeAdjacents ? ifThen(distinct(), ifElse) : ifElse; ifElse.wSetVisitor2(traverseAll(result, includeAdjacents)); return result; } public IBinaryVisitor bottomUp(IVisitor visitor, boolean includeAdjacents) { IBinaryVisitor sequence = sequence(null, visitor); IBinaryVisitor result = includeAdjacents ? ifThen(distinct(), sequence) : sequence; sequence.wSetVisitor1(traverseAll(result, includeAdjacents)); return result; } public IBinaryVisitor downUp(IVisitor vBefore, IVisitor vAfter, boolean includeAdjacents) { IBinaryVisitor sequence = sequence(vBefore, null); IBinaryVisitor result = includeAdjacents ? ifThen(distinct(), sequence) : sequence; sequence.wSetVisitor2(sequence(traverseAll(result, includeAdjacents), vAfter)); return result; } public IBinaryVisitor downUpWhile(IVisitor vBefore, IVisitor vAfter, boolean includeAdjacents) { IBinaryVisitor result = ifThen( includeAdjacents ? sequence(distinct(), vBefore) : vBefore, null); result.wSetVisitor2(sequence(traverseAll(result, includeAdjacents), vAfter)); return result; } public IUnaryVisitor onceTopDown(IVisitor visitor, boolean includeAdjacents) { IBinaryVisitor ifElse = ifElse(visitor, null); IBinaryVisitor result = includeAdjacents ? sequence(distinct(), ifElse) : ifElse; ifElse.wSetVisitor2(traverseOne(result, includeAdjacents)); return result; } public IBinaryVisitor onceBottomUp(IVisitor visitor, boolean includeAdjacents) { IBinaryVisitor ifElse = ifElse(null, visitor); IBinaryVisitor result = includeAdjacents ? sequence(distinct(), ifElse) : ifElse; ifElse.wSetVisitor1(traverseOne(result, includeAdjacents)); return result; } public IUnaryVisitor spineTopDown(IVisitor visitor, boolean includeAdjacents) { IBinaryVisitor sequence = sequence(visitor, null); IBinaryVisitor result = includeAdjacents ? ifThen(distinct(), sequence) : sequence; sequence.wSetVisitor2( ifElse(traverseOne(result, includeAdjacents), traverseAll(failure(), includeAdjacents))); return result; } public IVisitor spineBottomUp(IVisitor visitor, boolean includeAdjacents) { IBinaryVisitor sequence = sequence(null, visitor); IBinaryVisitor result = includeAdjacents ? ifThen(distinct(), sequence) : sequence; sequence.wSetVisitor1( ifElse(traverseOne(result, includeAdjacents), traverseAll(failure(), includeAdjacents))); return result; } //derived fixpoint traversal strategies public IVisitor reduce(IVisitor visitor) { IBinaryVisitor rec = concurrentSequence(visitor, null); rec.wSetVisitor2(rec); return concurrentSequence(visitor, tryPrune(rec)); } public IVisitor outermost(IVisitor visitor) { IUnaryVisitor result = concurrentTopDown(null, false); result.wSetVisitor1(tryPrune(concurrentSequence(visitor, result))); return result; } public IVisitor innermost(IVisitor visitor) { IBinaryVisitor result = bottomUp(null, false); result.wSetVisitor2(tryPrune(concurrentSequence(visitor, result))); return result; } }