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