1 // 2 // ANTLRTreeIterator.m 3 // ANTLR 4 // 5 // Created by Ian Michell on 26/04/2010. 6 // Copyright (c) 2010 Ian Michell 2010 Alan Condit 7 // All rights reserved. 8 // 9 // Redistribution and use in source and binary forms, with or without 10 // modification, are permitted provided that the following conditions 11 // are met: 12 // 1. Redistributions of source code must retain the above copyright 13 // notice, this list of conditions and the following disclaimer. 14 // 2. Redistributions in binary form must reproduce the above copyright 15 // notice, this list of conditions and the following disclaimer in the 16 // documentation and/or other materials provided with the distribution. 17 // 3. The name of the author may not be used to endorse or promote products 18 // derived from this software without specific prior written permission. 19 // 20 // THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 21 // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 22 // OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 23 // IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 24 // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 25 // NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 29 // THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 31 32 #import "ANTLRTreeIterator.h" 33 #import "ANTLRCommonTreeAdaptor.h" 34 35 @implementation ANTLRTreeIterator 36 37 + (ANTLRTreeIterator *) newANTRLTreeIterator 38 { 39 return [[ANTLRTreeIterator alloc] init]; 40 } 41 42 + (ANTLRTreeIterator *) newANTRLTreeIteratorWithAdaptor:(ANTLRCommonTreeAdaptor *)adaptor 43 andTree:(id<ANTLRBaseTree>)tree 44 { 45 return [[ANTLRTreeIterator alloc] initWithTreeAdaptor:adaptor andTree:tree]; 46 } 47 48 - (id) init 49 { 50 self = [super init]; 51 if ( self != nil ) { 52 firstTime = YES; 53 nodes = [[ANTLRFastQueue newANTLRFastQueue] retain]; 54 down = [[adaptor createTree:ANTLRTokenTypeDOWN Text:@"DOWN"] retain]; 55 up = [[adaptor createTree:ANTLRTokenTypeUP Text:@"UP"] retain]; 56 eof = [[adaptor createTree:ANTLRTokenTypeEOF Text:@"EOF"] retain]; 57 tree = eof; 58 root = eof; 59 } 60 return self; 61 } 62 63 -(id) initWithTree:(id<ANTLRBaseTree>) t 64 { 65 self = [super init]; 66 if ( self != nil ) { 67 firstTime = YES; 68 adaptor = [[ANTLRCommonTreeAdaptor newTreeAdaptor] retain]; 69 tree = [t retain]; 70 root = t; 71 nodes = [[ANTLRFastQueue newANTLRFastQueue] retain]; 72 down = [[adaptor createTree:ANTLRTokenTypeDOWN Text:@"DOWN"] retain]; 73 up = [[adaptor createTree:ANTLRTokenTypeUP Text:@"UP"] retain]; 74 eof = [[adaptor createTree:ANTLRTokenTypeEOF Text:@"EOF"] retain]; 75 } 76 return self; 77 } 78 79 -(id) initWithTreeAdaptor:(id<ANTLRTreeAdaptor>)a andTree:(id<ANTLRBaseTree>)t 80 { 81 self = [super init]; 82 if ( self != nil ) { 83 firstTime = YES; 84 adaptor = [a retain]; 85 tree = [t retain]; 86 root = t; 87 nodes = [[ANTLRFastQueue newANTLRFastQueue] retain]; 88 down = [[adaptor createTree:ANTLRTokenTypeDOWN Text:@"DOWN"] retain]; 89 up = [[adaptor createTree:ANTLRTokenTypeUP Text:@"UP"] retain]; 90 eof = [[adaptor createTree:ANTLRTokenTypeEOF Text:@"EOF"] retain]; 91 } 92 return self; 93 } 94 95 - (void)dealloc 96 { 97 #ifdef DEBUG_DEALLOC 98 NSLog( @"called dealloc in ANTLRTreeIterator" ); 99 #endif 100 if ( adaptor ) [adaptor release]; 101 if ( nodes ) [nodes release]; 102 if ( tree && tree != eof ) [tree release]; 103 if ( root && root != eof && root != tree ) [root release]; 104 if ( down ) [down release]; 105 if ( up ) [up release]; 106 if ( eof ) [eof release]; 107 [super dealloc]; 108 } 109 110 - (void)reset 111 { 112 firstTime = YES; 113 tree = root; 114 [nodes clear]; 115 } 116 117 -(BOOL) hasNext 118 { 119 if ( firstTime ) { 120 return root != nil; 121 } 122 if ( nodes && [nodes size] > 0) { 123 return YES; 124 } 125 if ( tree == nil ) { 126 return NO; 127 } 128 if ( [adaptor getChildCount:tree] > 0 ) { 129 return YES; 130 } 131 return [adaptor getParent:tree] != nil; 132 } 133 134 -(id) nextObject 135 { 136 // is this the first time we are using this method? 137 if ( firstTime ) { 138 firstTime = NO; 139 if ( [adaptor getChildCount:tree] == 0 ) { 140 [nodes addObject:eof]; 141 return tree; 142 } 143 return tree; 144 } 145 // do we have any objects queued up? 146 if ( nodes && [nodes size] > 0 ) { 147 return [nodes remove]; 148 } 149 // no nodes left? 150 if ( tree == nil ) { 151 return eof; 152 } 153 if ( [adaptor getChildCount:tree] > 0 ) { 154 tree = [adaptor getChild:tree At:0]; 155 [nodes addObject:tree]; // real node is next after down 156 return self.down; 157 } 158 // if no children, look for next sibling of ancestor 159 id<ANTLRBaseTree> parent = [adaptor getParent:tree]; 160 while (parent != nil && ([adaptor getChildIndex:tree] + 1) >= [adaptor getChildCount:parent]) { 161 [nodes addObject:up]; 162 tree = parent; 163 parent = [adaptor getParent:tree]; 164 } 165 if ( parent == nil ) { 166 tree = nil; 167 [nodes addObject:self.eof]; 168 return [nodes remove]; 169 } 170 // must have found a node with an unvisited sibling 171 // move to it and return it 172 NSInteger nextSiblingIndex = [adaptor getChildIndex:tree] + 1; 173 tree = [adaptor getChild:parent At:nextSiblingIndex]; 174 [nodes addObject:tree]; 175 return [nodes remove]; 176 } 177 178 -(NSArray *) allObjects 179 { 180 AMutableArray *array = [AMutableArray arrayWithCapacity:10]; 181 while ( [self hasNext] ) { 182 [array addObject:[self nextObject]]; 183 } 184 return array; 185 } 186 187 - (void)remove 188 { 189 @throw [ANTLRRuntimeException newException:@"ANTLRUnsupportedOperationException"]; 190 } 191 192 @synthesize firstTime; 193 @synthesize adaptor; 194 @synthesize root; 195 @synthesize tree; 196 @synthesize nodes; 197 198 @synthesize up; 199 @synthesize down; 200 @synthesize eof; 201 202 @end 203