| // |
| // TreeIterator.m |
| // ANTLR |
| // |
| // Created by Ian Michell on 26/04/2010. |
| // Copyright (c) 2010 Ian Michell 2010 Alan Condit |
| // All rights reserved. |
| // |
| // Redistribution and use in source and binary forms, with or without |
| // modification, are permitted provided that the following conditions |
| // are met: |
| // 1. Redistributions of source code must retain the above copyright |
| // notice, this list of conditions and the following disclaimer. |
| // 2. Redistributions in binary form must reproduce the above copyright |
| // notice, this list of conditions and the following disclaimer in the |
| // documentation and/or other materials provided with the distribution. |
| // 3. The name of the author may not be used to endorse or promote products |
| // derived from this software without specific prior written permission. |
| // |
| // THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
| // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
| // OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
| // IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
| // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
| // NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
| // THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| |
| |
| #import "TreeIterator.h" |
| #import "CommonTreeAdaptor.h" |
| |
| @implementation TreeIterator |
| |
| + (TreeIterator *) newANTRLTreeIterator |
| { |
| return [[TreeIterator alloc] init]; |
| } |
| |
| + (TreeIterator *) newANTRLTreeIteratorWithAdaptor:(CommonTreeAdaptor *)adaptor |
| andTree:(id<BaseTree>)tree |
| { |
| return [[TreeIterator alloc] initWithTreeAdaptor:adaptor andTree:tree]; |
| } |
| |
| - (id) init |
| { |
| self = [super init]; |
| if ( self != nil ) { |
| firstTime = YES; |
| nodes = [[FastQueue newFastQueue] retain]; |
| down = [[adaptor createTree:TokenTypeDOWN Text:@"DOWN"] retain]; |
| up = [[adaptor createTree:TokenTypeUP Text:@"UP"] retain]; |
| eof = [[adaptor createTree:TokenTypeEOF Text:@"EOF"] retain]; |
| tree = eof; |
| root = eof; |
| } |
| return self; |
| } |
| |
| -(id) initWithTree:(id<BaseTree>) t |
| { |
| self = [super init]; |
| if ( self != nil ) { |
| firstTime = YES; |
| adaptor = [[CommonTreeAdaptor newTreeAdaptor] retain]; |
| tree = [t retain]; |
| root = t; |
| nodes = [[FastQueue newFastQueue] retain]; |
| down = [[adaptor createTree:TokenTypeDOWN Text:@"DOWN"] retain]; |
| up = [[adaptor createTree:TokenTypeUP Text:@"UP"] retain]; |
| eof = [[adaptor createTree:TokenTypeEOF Text:@"EOF"] retain]; |
| } |
| return self; |
| } |
| |
| -(id) initWithTreeAdaptor:(id<TreeAdaptor>)a andTree:(id<BaseTree>)t |
| { |
| self = [super init]; |
| if ( self != nil ) { |
| firstTime = YES; |
| adaptor = [a retain]; |
| tree = [t retain]; |
| root = t; |
| nodes = [[FastQueue newFastQueue] retain]; |
| down = [[adaptor createTree:TokenTypeDOWN Text:@"DOWN"] retain]; |
| up = [[adaptor createTree:TokenTypeUP Text:@"UP"] retain]; |
| eof = [[adaptor createTree:TokenTypeEOF Text:@"EOF"] retain]; |
| } |
| return self; |
| } |
| |
| - (void)dealloc |
| { |
| #ifdef DEBUG_DEALLOC |
| NSLog( @"called dealloc in TreeIterator" ); |
| #endif |
| if ( adaptor ) [adaptor release]; |
| if ( nodes ) [nodes release]; |
| if ( tree && tree != eof ) [tree release]; |
| if ( root && root != eof && root != tree ) [root release]; |
| if ( down ) [down release]; |
| if ( up ) [up release]; |
| if ( eof ) [eof release]; |
| [super dealloc]; |
| } |
| |
| - (void)reset |
| { |
| firstTime = YES; |
| tree = root; |
| [nodes clear]; |
| } |
| |
| -(BOOL) hasNext |
| { |
| if ( firstTime ) { |
| return root != nil; |
| } |
| if ( nodes && [nodes size] > 0) { |
| return YES; |
| } |
| if ( tree == nil ) { |
| return NO; |
| } |
| if ( [adaptor getChildCount:tree] > 0 ) { |
| return YES; |
| } |
| return [adaptor getParent:tree] != nil; |
| } |
| |
| -(id) nextObject |
| { |
| // is this the first time we are using this method? |
| if ( firstTime ) { |
| firstTime = NO; |
| if ( [adaptor getChildCount:tree] == 0 ) { |
| [nodes addObject:eof]; |
| return tree; |
| } |
| return tree; |
| } |
| // do we have any objects queued up? |
| if ( nodes && [nodes size] > 0 ) { |
| return [nodes remove]; |
| } |
| // no nodes left? |
| if ( tree == nil ) { |
| return eof; |
| } |
| if ( [adaptor getChildCount:tree] > 0 ) { |
| tree = [adaptor getChild:tree At:0]; |
| [nodes addObject:tree]; // real node is next after down |
| return self.down; |
| } |
| // if no children, look for next sibling of ancestor |
| id<BaseTree> parent = [adaptor getParent:tree]; |
| while (parent != nil && ([adaptor getChildIndex:tree] + 1) >= [adaptor getChildCount:parent]) { |
| [nodes addObject:up]; |
| tree = parent; |
| parent = [adaptor getParent:tree]; |
| } |
| if ( parent == nil ) { |
| tree = nil; |
| [nodes addObject:self.eof]; |
| return [nodes remove]; |
| } |
| // must have found a node with an unvisited sibling |
| // move to it and return it |
| NSInteger nextSiblingIndex = [adaptor getChildIndex:tree] + 1; |
| tree = [adaptor getChild:parent At:nextSiblingIndex]; |
| [nodes addObject:tree]; |
| return [nodes remove]; |
| } |
| |
| -(NSArray *) allObjects |
| { |
| AMutableArray *array = [AMutableArray arrayWithCapacity:10]; |
| while ( [self hasNext] ) { |
| [array addObject:[self nextObject]]; |
| } |
| return array; |
| } |
| |
| - (void)remove |
| { |
| @throw [RuntimeException newException:@"UnsupportedOperationException"]; |
| } |
| |
| @synthesize firstTime; |
| @synthesize adaptor; |
| @synthesize root; |
| @synthesize tree; |
| @synthesize nodes; |
| |
| @synthesize up; |
| @synthesize down; |
| @synthesize eof; |
| |
| @end |