1 // [The "BSD licence"] 2 // Copyright (c) 2006-2007 Kay Roepke 2010 Alan Condit 3 // All rights reserved. 4 // 5 // Redistribution and use in source and binary forms, with or without 6 // modification, are permitted provided that the following conditions 7 // are met: 8 // 1. Redistributions of source code must retain the above copyright 9 // notice, this list of conditions and the following disclaimer. 10 // 2. Redistributions in binary form must reproduce the above copyright 11 // notice, this list of conditions and the following disclaimer in the 12 // documentation and/or other materials provided with the distribution. 13 // 3. The name of the author may not be used to endorse or promote products 14 // derived from this software without specific prior written permission. 15 // 16 // THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17 // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18 // OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19 // IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20 // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 21 // NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25 // THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 27 #import "ANTLRRewriteRuleElementStream.h" 28 29 @implementation ANTLRRewriteRuleElementStream 30 31 @synthesize cursor; 32 @synthesize dirty; 33 @synthesize isSingleElement; 34 @synthesize singleElement; 35 @synthesize elements; 36 @synthesize elementDescription; 37 @synthesize treeAdaptor; 38 39 + (ANTLRRewriteRuleElementStream *) newANTLRRewriteRuleElementStream:(id<ANTLRTreeAdaptor>)aTreeAdaptor 40 description:(NSString *)anElementDescription 41 { 42 return [[ANTLRRewriteRuleElementStream alloc] initWithTreeAdaptor:aTreeAdaptor 43 description:anElementDescription]; 44 } 45 46 + (ANTLRRewriteRuleElementStream *) newANTLRRewriteRuleElementStream:(id<ANTLRTreeAdaptor>)aTreeAdaptor 47 description:(NSString *)anElementDescription 48 element:(id)anElement 49 { 50 return [[ANTLRRewriteRuleElementStream alloc] initWithTreeAdaptor:aTreeAdaptor 51 description:anElementDescription 52 element:anElement]; 53 } 54 55 + (ANTLRRewriteRuleElementStream *) newANTLRRewriteRuleElementStream:(id<ANTLRTreeAdaptor>)aTreeAdaptor 56 description:(NSString *)anElementDescription 57 elements:(NSArray *)theElements; 58 { 59 return [[ANTLRRewriteRuleElementStream alloc] initWithTreeAdaptor:aTreeAdaptor 60 description:anElementDescription 61 elements:theElements]; 62 } 63 64 - (id) initWithTreeAdaptor:(id<ANTLRTreeAdaptor>)aTreeAdaptor description:(NSString *)anElementDescription 65 { 66 if ((self = [super init]) != nil) { 67 cursor = 0; 68 dirty = NO; 69 [self setDescription:anElementDescription]; 70 [self setTreeAdaptor:aTreeAdaptor]; 71 dirty = NO; 72 isSingleElement = YES; 73 singleElement = nil; 74 elements = nil; 75 } 76 return self; 77 } 78 79 - (id) initWithTreeAdaptor:(id<ANTLRTreeAdaptor>)aTreeAdaptor description:(NSString *)anElementDescription element:(id)anElement 80 { 81 if ((self = [super init]) != nil) { 82 cursor = 0; 83 dirty = NO; 84 [self setDescription:anElementDescription]; 85 [self setTreeAdaptor:aTreeAdaptor]; 86 dirty = NO; 87 isSingleElement = YES; 88 singleElement = nil; 89 elements = nil; 90 [self addElement:anElement]; 91 } 92 return self; 93 } 94 95 - (id) initWithTreeAdaptor:(id<ANTLRTreeAdaptor>)aTreeAdaptor description:(NSString *)anElementDescription elements:(NSArray *)theElements 96 { 97 self = [super init]; 98 if (self) { 99 cursor = 0; 100 dirty = NO; 101 [self setDescription:anElementDescription]; 102 [self setTreeAdaptor:aTreeAdaptor]; 103 dirty = NO; 104 singleElement = nil; 105 isSingleElement = NO; 106 elements = [[AMutableArray arrayWithArray:theElements] retain]; 107 } 108 return self; 109 } 110 111 - (void) dealloc 112 { 113 #ifdef DEBUG_DEALLOC 114 NSLog( @"called dealloc in ANTLRRewriteRuleElementStream" ); 115 #endif 116 if ( singleElement && isSingleElement ) [singleElement release]; 117 else if ( elements && !isSingleElement ) [elements release]; 118 [self setDescription:nil]; 119 [self setTreeAdaptor:nil]; 120 [super dealloc]; 121 } 122 123 - (void)reset 124 { 125 cursor = 0; 126 dirty = YES; 127 } 128 129 - (id<ANTLRTreeAdaptor>) getTreeAdaptor 130 { 131 return treeAdaptor; 132 } 133 134 - (void) setTreeAdaptor:(id<ANTLRTreeAdaptor>)aTreeAdaptor 135 { 136 if (treeAdaptor != aTreeAdaptor) { 137 if ( treeAdaptor ) [treeAdaptor release]; 138 treeAdaptor = aTreeAdaptor; 139 [treeAdaptor retain]; 140 } 141 } 142 143 - (void) addElement: (id)anElement 144 { 145 if (anElement == nil) 146 return; 147 if (elements != nil) { 148 [elements addObject:anElement]; 149 return; 150 } 151 if (singleElement == nil) { 152 singleElement = anElement; 153 singleElement = [anElement retain]; 154 return; 155 } 156 isSingleElement = NO; 157 elements = [[AMutableArray arrayWithCapacity:5] retain]; 158 [elements addObject:singleElement]; 159 singleElement = nil; // balance previous retain in initializer/addElement 160 [elements addObject:anElement]; 161 } 162 163 - (void) setElement: (id)anElement 164 { 165 if (anElement == nil) 166 return; 167 if (elements != nil) { 168 [elements addObject:anElement]; 169 return; 170 } 171 if (singleElement == nil) { 172 singleElement = anElement; 173 singleElement = [anElement retain]; 174 return; 175 } 176 isSingleElement = NO; 177 elements = [[AMutableArray arrayWithCapacity:5] retain]; 178 [elements addObject:singleElement]; 179 singleElement = nil; // balance previous retain in initializer/addElement 180 [elements addObject:anElement]; 181 } 182 183 - (id<ANTLRBaseTree>) nextTree 184 { 185 NSInteger n = [self size]; 186 if ( dirty && (cursor >= 0 && n == 1)) { 187 // if out of elements and size is 1, dup 188 id element = [self _next]; 189 return [self copyElement:element]; 190 } 191 // test size above then fetch 192 id element = [self _next]; 193 return element; 194 } 195 196 - (id) _next // internal: TODO: redesign if necessary. maybe delegate 197 { 198 NSInteger n = [self size]; 199 if (n == 0) { 200 @throw [NSException exceptionWithName:@"RewriteEmptyStreamException" reason:nil userInfo:nil];// TODO: fill in real exception 201 } 202 if ( cursor >= n ) { 203 if ( n == 1 ) { 204 return [self toTree:singleElement]; // will be dup'ed in -next 205 } 206 @throw [NSException exceptionWithName:@"RewriteCardinalityException" reason:nil userInfo:nil];// TODO: fill in real exception 207 } 208 if (singleElement != nil) { 209 cursor++; 210 return [self toTree:singleElement]; 211 } 212 id el = [elements objectAtIndex:cursor]; 213 cursor++; 214 return [self toTree:el]; 215 } 216 217 - (BOOL) hasNext 218 { 219 return (singleElement != nil && cursor < 1) || 220 (elements != nil && cursor < [elements count]); 221 } 222 223 - (NSInteger) size 224 { 225 NSInteger n = 0; 226 if (singleElement != nil) 227 n = 1; 228 if (elements != nil) 229 return [elements count]; 230 return n; 231 } 232 233 - (id) copyElement:(id)element 234 { 235 [self doesNotRecognizeSelector:_cmd]; // subclass responsibility 236 return nil; 237 } 238 239 - (id<ANTLRBaseTree>) toTree:(id)element 240 { 241 return element; 242 } 243 244 - (NSString *) getDescription 245 { 246 return elementDescription; 247 } 248 249 - (void) setDescription:(NSString *) description 250 { 251 if ( description != nil && description != elementDescription ) { 252 if (elementDescription != nil) [elementDescription release]; 253 elementDescription = [NSString stringWithString:description]; 254 [elementDescription retain]; 255 } 256 } 257 258 @end 259