001package de.monochromata.anaphors.ast.chain; 002 003import static java.util.Collections.singletonList; 004import static java.util.stream.Collectors.toList; 005 006import java.util.List; 007import java.util.function.Predicate; 008import java.util.stream.Stream; 009import java.util.stream.Stream.Builder; 010 011import de.monochromata.anaphors.ast.ASTBasedAnaphora; 012import de.monochromata.anaphors.ast.relatedexp.RelatedExpression; 013 014public interface ChainTraversal { 015 016 /** 017 * @param <N> The node type in the AST 018 * @param <E> The expression type 019 * @param <T> The type type 020 * @param <B> The binding type 021 * @param <TB> The type binding type 022 * @param <S> The scope type (optional) 023 * @param <I> The type used to represent identifiers 024 * @param <QI> The type used to represent qualified identifiers 025 * @param <AT> The type used for attachments to chain elements that have an 026 * anaphor part. The attachment may be used to stored e.g. an old 027 * anaphora relation. 028 * @param <R> The sub-type of related expression to use 029 * @param <A> The sub-type of AST-based anaphora to use 030 * @param <C> The sub-type of chain element to use 031 * @throws IllegalStateException If no anaphor element could be found. 032 */ 033 static <N, E, T, B, TB extends B, S, I, QI, AT, R extends RelatedExpression<N, T, B, TB, S, QI, R>, A extends ASTBasedAnaphora<N, E, T, B, TB, S, I, QI, R, A>, C extends ChainElement<N, E, T, B, TB, S, I, QI, AT, R, A, C>> List<C> getAnaphorElementsForRelatedExpressionElement( 034 final C relatedExpressionElement) { 035 final Builder<C> builder = Stream.builder(); 036 collectAnaphorElements(relatedExpressionElement.next, builder, next -> next.anaphor != null, 037 next -> next.relatedExpression == null); 038 final List<C> anaphorElements = builder.build().collect(toList()); 039 if (anaphorElements.isEmpty()) { 040 throw new IllegalStateException("No anaphor elements found"); 041 } 042 return anaphorElements; 043 } 044 045 /** 046 * @param <N> The node type in the AST 047 * @param <E> The expression type 048 * @param <T> The type type 049 * @param <B> The binding type 050 * @param <TB> The type binding type 051 * @param <S> The scope type (optional) 052 * @param <I> The type used to represent identifiers 053 * @param <QI> The type used to represent qualified identifiers 054 * @param <AT> The type used for attachments to chain elements that have an 055 * anaphor part. The attachment may be used to stored e.g. an old 056 * anaphora relation. 057 * @param <R> The sub-type of related expression to use 058 * @param <A> The sub-type of AST-based anaphora to use 059 * @param <C> The sub-type of chain element to use 060 * @throws IllegalStateException If no related expression element could be 061 * found. 062 */ 063 static <N, E, T, B, TB extends B, S, I, QI, AT, R extends RelatedExpression<N, T, B, TB, S, QI, R>, A extends ASTBasedAnaphora<N, E, T, B, TB, S, I, QI, R, A>, C extends ChainElement<N, E, T, B, TB, S, I, QI, AT, R, A, C>> C getRelatedExpressionElementForAnaphorElement( 064 final C anaphorElement) { 065 C current = anaphorElement; 066 while (current != null) { 067 if (current.relatedExpression != null) { 068 return current; 069 } 070 current = current.previous; 071 } 072 throw new IllegalStateException("No related expression element found"); 073 } 074 075 /** 076 * @param <N> The node type in the AST 077 * @param <E> The expression type 078 * @param <T> The type type 079 * @param <B> The binding type 080 * @param <TB> The type binding type 081 * @param <S> The scope type (optional) 082 * @param <I> The type used to represent identifiers 083 * @param <QI> The type used to represent qualified identifiers 084 * @param <AT> The type used for attachments to chain elements that have an 085 * anaphor part. The attachment may be used to stored e.g. an old 086 * anaphora relation. 087 * @param <R> The sub-type of related expression to use 088 * @param <A> The sub-type of AST-based anaphora to use 089 * @param <C> The sub-type of chain element to use 090 */ 091 static <N, E, T, B, TB extends B, S, I, QI, AT, R extends RelatedExpression<N, T, B, TB, S, QI, R>, A extends ASTBasedAnaphora<N, E, T, B, TB, S, I, QI, R, A>, C extends ChainElement<N, E, T, B, TB, S, I, QI, AT, R, A, C>> Stream<C> getRelatedExpressionElements( 092 final C root) { 093 return getElements(root, next -> next.relatedExpression != null); 094 } 095 096 /** 097 * @param <N> The node type in the AST 098 * @param <E> The expression type 099 * @param <T> The type type 100 * @param <B> The binding type 101 * @param <TB> The type binding type 102 * @param <S> The scope type (optional) 103 * @param <I> The type used to represent identifiers 104 * @param <QI> The type used to represent qualified identifiers 105 * @param <AT> The type used for attachments to chain elements that have an 106 * anaphor part. The attachment may be used to stored e.g. an old 107 * anaphora relation. 108 * @param <R> The sub-type of related expression to use 109 * @param <A> The sub-type of AST-based anaphora to use 110 * @param <C> The sub-type of chain element to use 111 */ 112 static <N, E, T, B, TB extends B, S, I, QI, AT, R extends RelatedExpression<N, T, B, TB, S, QI, R>, A extends ASTBasedAnaphora<N, E, T, B, TB, S, I, QI, R, A>, C extends ChainElement<N, E, T, B, TB, S, I, QI, AT, R, A, C>> Stream<C> getAnaphorElements( 113 final C root) { 114 return getElements(root, next -> next.anaphor != null); 115 } 116 117 /** 118 * @param <N> The node type in the AST 119 * @param <E> The expression type 120 * @param <T> The type type 121 * @param <B> The binding type 122 * @param <TB> The type binding type 123 * @param <S> The scope type (optional) 124 * @param <I> The type used to represent identifiers 125 * @param <QI> The type used to represent qualified identifiers 126 * @param <AT> The type used for attachments to chain elements that have an 127 * anaphor part. The attachment may be used to stored e.g. an old 128 * anaphora relation. 129 * @param <R> The sub-type of related expression to use 130 * @param <A> The sub-type of AST-based anaphora to use 131 * @param <C> The sub-type of chain element to use 132 */ 133 static <N, E, T, B, TB extends B, S, I, QI, AT, R extends RelatedExpression<N, T, B, TB, S, QI, R>, A extends ASTBasedAnaphora<N, E, T, B, TB, S, I, QI, R, A>, C extends ChainElement<N, E, T, B, TB, S, I, QI, AT, R, A, C>> Stream<C> getElements( 134 final C root, final Predicate<C> predicate) { 135 final Builder<C> builder = Stream.builder(); 136 collectAnaphorElements(singletonList(root), builder, predicate); 137 return builder.build(); 138 } 139 140 /** 141 * @param <N> The node type in the AST 142 * @param <E> The expression type 143 * @param <T> The type type 144 * @param <B> The binding type 145 * @param <TB> The type binding type 146 * @param <S> The scope type (optional) 147 * @param <I> The type used to represent identifiers 148 * @param <QI> The type used to represent qualified identifiers 149 * @param <AT> The type used for attachments to chain elements that have an 150 * anaphor part. The attachment may be used to stored e.g. an old 151 * anaphora relation. 152 * @param <R> The sub-type of related expression to use 153 * @param <A> The sub-type of AST-based anaphora to use 154 * @param <C> The sub-type of chain element to use 155 */ 156 static <N, E, T, B, TB extends B, S, I, QI, AT, R extends RelatedExpression<N, T, B, TB, S, QI, R>, A extends ASTBasedAnaphora<N, E, T, B, TB, S, I, QI, R, A>, C extends ChainElement<N, E, T, B, TB, S, I, QI, AT, R, A, C>> void collectAnaphorElements( 157 final List<C> nextElements, final Builder<C> builder, final Predicate<C> predicate) { 158 collectAnaphorElements(nextElements, builder, predicate, unused -> true); 159 } 160 161 /** 162 * @param <N> The node type in the AST 163 * @param <E> The expression type 164 * @param <T> The type type 165 * @param <B> The binding type 166 * @param <TB> The type binding type 167 * @param <S> The scope type (optional) 168 * @param <I> The type used to represent identifiers 169 * @param <QI> The type used to represent qualified identifiers 170 * @param <AT> The type used for attachments to chain elements that have an 171 * anaphor part. The attachment may be used to stored e.g. an old 172 * anaphora relation. 173 * @param <R> The sub-type of related expression to use 174 * @param <A> The sub-type of AST-based anaphora to use 175 * @param <C> The sub-type of chain element to use 176 */ 177 static <N, E, T, B, TB extends B, S, I, QI, AT, R extends RelatedExpression<N, T, B, TB, S, QI, R>, A extends ASTBasedAnaphora<N, E, T, B, TB, S, I, QI, R, A>, C extends ChainElement<N, E, T, B, TB, S, I, QI, AT, R, A, C>> void collectAnaphorElements( 178 final List<C> nextElements, final Builder<C> builder, final Predicate<C> shouldAddElement, 179 final Predicate<C> shouldContinue) { 180 for (final C next : nextElements) { 181 if (shouldAddElement.test(next)) { 182 builder.add(next); 183 } 184 if (shouldContinue.test(next)) { 185 collectAnaphorElements(next.next, builder, shouldAddElement); 186 } 187 } 188 } 189 190}